rdb support sendable

Signed-off-by: changjiaxing <changjiaxing2@huawei.com>
Change-Id: Id84eff0a2a415fbfccca8487906aa8cd7b4bf3a1
This commit is contained in:
changjiaxing 2024-07-09 16:07:35 +08:00
parent 2a83995e30
commit ed0902e095
26 changed files with 1212 additions and 119 deletions

View File

@ -87,7 +87,8 @@
"//foundation/distributeddatamgr/relational_store/frameworks/js/napi/rdb:napi_rdb",
"//foundation/distributeddatamgr/relational_store/frameworks/js/napi/relationalstore:relationalstore",
"//foundation/distributeddatamgr/relational_store/frameworks/js/napi/cloud_extension:cloudextension",
"//foundation/distributeddatamgr/relational_store/frameworks/js/napi/common:commontype_napi"
"//foundation/distributeddatamgr/relational_store/frameworks/js/napi/common:commontype_napi",
"//foundation/distributeddatamgr/relational_store/frameworks/js/napi/sendablerelationalstore:sendablerelationalstore"
],
"inner_kits": [
{

View File

@ -32,6 +32,13 @@ static inline OHOS::HiviewDFX::HiLogLabel LogLabel()
return { LOG_CORE, 0xD001656, "RdbNdk" };
}
} // namespace RdbNdk
namespace SendableRdb {
static inline OHOS::HiviewDFX::HiLogLabel LogLabel()
{
return { LOG_CORE, 0xD001650, "SRdb" };
}
} // namespace Rdb
} // namespace OHOS
#define LOG_DEBUG(fmt, ...) \

View File

@ -0,0 +1,98 @@
/*
* Copyright (c) 2024 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef DISTRIBUTEDDATAMGR_APPDATAMGR_JS_SENDABLE_UTILS_H
#define DISTRIBUTEDDATAMGR_APPDATAMGR_JS_SENDABLE_UTILS_H
#include <cstdint>
#include "js_utils.h"
#include "napi/native_common.h"
#include "napi/native_node_api.h"
namespace OHOS {
namespace AppDataMgrJsKit {
namespace JSUtils {
#define DECLARE_SENDABLE_PROPERTY(env, key, value) \
napi_property_descriptor(DECLARE_NAPI_DEFAULT_PROPERTY((key), Convert2Sendable((env), (value))))
int32_t Convert2Sendable(napi_env env, std::string value, napi_value &output);
int32_t Convert2Sendable(napi_env env, bool value, napi_value &output);
int32_t Convert2Sendable(napi_env env, double value, napi_value &output);
napi_value Convert2Sendable(napi_env env, const std::string &value);
napi_value Convert2Sendable(napi_env env, const std::vector<uint8_t> &value);
napi_value Convert2Sendable(napi_env env, const std::vector<float> &value);
napi_value Convert2Sendable(napi_env env, int32_t value);
napi_value Convert2Sendable(napi_env env, uint32_t value);
napi_value Convert2Sendable(napi_env env, int64_t value);
napi_value Convert2Sendable(napi_env env, double value);
napi_value Convert2Sendable(napi_env env, bool value);
napi_value Convert2Sendable(napi_env env, const std::monostate &value);
template<typename T>
napi_value Convert2Sendable(napi_env env, const T &value);
template<typename T>
napi_value Convert2Sendable(napi_env env, const std::vector<T> &value);
template<typename... Types>
napi_value Convert2Sendable(napi_env env, const std::variant<Types...> &value);
template<typename T>
napi_value GetSendableValue(napi_env env, const T &value)
{
return nullptr;
}
template<typename T, typename First, typename... Types>
napi_value GetSendableValue(napi_env env, const T &value)
{
auto *val = std::get_if<First>(&value);
if (val != nullptr) {
return Convert2Sendable(env, *val);
}
return GetSendableValue<T, Types...>(env, value);
}
napi_value ToSendableObject(napi_env env, napi_value jsValue);
napi_value ToSendableArray(napi_env env, napi_value jsValue);
napi_value ToSendableTypedArray(napi_env env, napi_value jsValue);
napi_value Convert2Sendable(napi_env env, napi_value jsValue);
} // namespace JSUtils
template<typename T>
napi_value JSUtils::Convert2Sendable(napi_env env, const std::vector<T> &value)
{
napi_value jsValue;
napi_status status = napi_create_sendable_array_with_length(env, value.size(), &jsValue);
if (status != napi_ok) {
return nullptr;
}
for (size_t i = 0; i < value.size(); ++i) {
napi_set_element(env, jsValue, i, Convert2Sendable(env, value[i]));
}
return jsValue;
}
template<typename... Types>
napi_value JSUtils::Convert2Sendable(napi_env env, const std::variant<Types...> &value)
{
return GetSendableValue<decltype(value), Types...>(env, value);
}
} // namespace AppDataMgrJsKit
} // namespace OHOS
#endif // DISTRIBUTEDDATAMGR_APPDATAMGR_JS_SENDABLE_UTILS_H

View File

@ -35,7 +35,16 @@
namespace OHOS {
namespace AppDataMgrJsKit {
namespace JSUtils {
#define DECLARE_JS_PROPERTY(env, key, value) \
napi_property_descriptor(DECLARE_NAPI_DEFAULT_PROPERTY((key), Convert2JSValue((env), (value))))
#define ASSERT(condition, message, retVal) \
do { \
if (!(condition)) { \
LOG_ERROR("test (" #condition ") failed: " message); \
return retVal; \
} \
} while (0)
static constexpr int OK = 0;
static constexpr int ERR = -1;
static constexpr uint32_t ASYNC_RST_SIZE = 2;
@ -48,10 +57,6 @@ struct JsFeatureSpace {
bool isComponent;
};
int32_t Convert2ValueExt(napi_env env, napi_value jsValue, uint32_t &output);
int32_t Convert2ValueExt(napi_env env, napi_value jsValue, int32_t &output);
int32_t Convert2ValueExt(napi_env env, napi_value jsValue, int64_t &output);
int32_t Convert2Value(napi_env env, napi_value jsValue, napi_value &output);
int32_t Convert2Value(napi_env env, napi_value jsValue, bool &output);
int32_t Convert2Value(napi_env env, napi_value jsValue, double &output);
@ -73,6 +78,10 @@ int32_t Convert2Value(napi_env env, napi_value jsValue, T &output);
template<typename T>
int32_t Convert2ValueExt(napi_env env, napi_value jsValue, T &output);
int32_t Convert2ValueExt(napi_env env, napi_value jsValue, uint32_t &output);
int32_t Convert2ValueExt(napi_env env, napi_value jsValue, int32_t &output);
int32_t Convert2ValueExt(napi_env env, napi_value jsValue, int64_t &output);
template<typename T>
int32_t Convert2Value(napi_env env, napi_value jsValue, std::vector<T> &value);
@ -94,7 +103,6 @@ int32_t Convert2JSValue(napi_env env, std::string value, napi_value &output);
int32_t Convert2JSValue(napi_env env, bool value, napi_value &output);
int32_t Convert2JSValue(napi_env env, double value, napi_value &output);
napi_value Convert2JSValue(napi_env env, const std::vector<std::string> &value);
napi_value Convert2JSValue(napi_env env, const std::string &value);
napi_value Convert2JSValue(napi_env env, const std::vector<uint8_t> &value);
napi_value Convert2JSValue(napi_env env, const std::vector<float> &value);
@ -199,6 +207,11 @@ inline int32_t SetNamedProperty(napi_env env, napi_value in, const std::string &
{
return napi_set_named_property(env, in, prop.c_str(), Convert2JSValue(env, value));
};
napi_value ToJsObject(napi_env env, napi_value sendableValue);
napi_value ToJsArray(napi_env env, napi_value sendableValue);
napi_value ToJsTypedArray(napi_env env, napi_value sendableValue);
napi_value Convert2JSValue(napi_env env, napi_value sendableValue);
} // namespace JSUtils
template<typename T>

View File

@ -0,0 +1,220 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define LOG_TAG "JSSendableUtils"
#include "js_sendable_utils.h"
#include <cstring>
#include "js_native_api.h"
#include "js_utils.h"
#include "logger.h"
#include "securec.h"
using namespace OHOS::Rdb;
namespace OHOS {
namespace AppDataMgrJsKit {
napi_value JSUtils::Convert2Sendable(napi_env env, const std::string &value)
{
return Convert2JSValue(env, value);
}
napi_value JSUtils::Convert2Sendable(napi_env env, const std::vector<uint8_t> &value)
{
napi_value jsValue = nullptr;
void *native = nullptr;
napi_value buffer = nullptr;
napi_status status = napi_create_sendable_arraybuffer(env, value.size(), &native, &buffer);
if (status != napi_ok) {
LOG_ERROR("napi_create_sendable_arraybuffer failed %{public}d", status);
return nullptr;
}
if (value.size() != 0) {
std::copy(value.begin(), value.end(), static_cast<uint8_t *>(native));
}
status = napi_create_sendable_typedarray(env, napi_uint8_array, value.size(), buffer, 0, &jsValue);
if (status != napi_ok) {
LOG_ERROR("napi_create_sendable_typedarray failed %{public}d", status);
return nullptr;
}
return jsValue;
}
napi_value JSUtils::Convert2Sendable(napi_env env, int32_t value)
{
return Convert2JSValue(env, value);
}
napi_value JSUtils::Convert2Sendable(napi_env env, uint32_t value)
{
return Convert2JSValue(env, value);
}
napi_value JSUtils::Convert2Sendable(napi_env env, int64_t value)
{
return Convert2JSValue(env, value);
}
napi_value JSUtils::Convert2Sendable(napi_env env, double value)
{
return Convert2JSValue(env, value);
}
napi_value JSUtils::Convert2Sendable(napi_env env, bool value)
{
return Convert2JSValue(env, value);
}
napi_value JSUtils::Convert2Sendable(napi_env env, const std::vector<float> &value)
{
napi_value jsValue = nullptr;
float *native = nullptr;
napi_value buffer = nullptr;
napi_status status = napi_create_sendable_arraybuffer(env, value.size() * sizeof(float), (void **)&native, &buffer);
if (status != napi_ok) {
LOG_ERROR("napi_create_sendable_arraybuffer failed %{public}d", status);
return nullptr;
}
if (value.size() != 0) {
std::copy(value.begin(), value.end(), static_cast<float *>(native));
}
status = napi_create_sendable_typedarray(env, napi_float32_array, value.size(), buffer, 0, &jsValue);
if (status != napi_ok) {
LOG_ERROR("napi_create_sendable_typedarray failed %{public}d", status);
return nullptr;
}
return jsValue;
}
int32_t JSUtils::Convert2Sendable(napi_env env, std::string value, napi_value &output)
{
return Convert2JSValue(env, value, output);
}
int32_t JSUtils::Convert2Sendable(napi_env env, bool value, napi_value &output)
{
return Convert2JSValue(env, value, output);
}
int32_t JSUtils::Convert2Sendable(napi_env env, double value, napi_value &output)
{
return Convert2JSValue(env, value, output);
}
napi_value JSUtils::Convert2Sendable(napi_env env, const std::monostate &value)
{
return Convert2JSValue(env, value);
}
napi_value JSUtils::ToSendableObject(napi_env env, napi_value jsValue)
{
LOG_DEBUG("jsObject -> sendableObject");
napi_value keys = nullptr;
napi_status status = napi_get_all_property_names(env, jsValue, napi_key_own_only,
static_cast<napi_key_filter>(napi_key_enumerable | napi_key_skip_symbols), napi_key_numbers_to_strings, &keys);
ASSERT(status == napi_ok, "napi_get_all_property_names failed", nullptr);
uint32_t length = 0;
status = napi_get_array_length(env, keys, &length);
ASSERT(status == napi_ok, "napi_get_array_length failed", nullptr);
std::vector<napi_property_descriptor> descriptors;
// keysHold guarantees that the string address is valid before create the sendable object.
std::vector<std::string> keysHold(length, "");
for (uint32_t i = 0; i < length; ++i) {
napi_value key = nullptr;
status = napi_get_element(env, keys, i, &key);
ASSERT(status == napi_ok, "napi_get_element failed", nullptr);
JSUtils::Convert2Value(env, key, keysHold[i]);
napi_value value = nullptr;
status = napi_get_named_property(env, jsValue, keysHold[i].c_str(), &value);
ASSERT(status == napi_ok, "napi_get_named_property failed", nullptr);
descriptors.emplace_back(DECLARE_SENDABLE_PROPERTY(env, keysHold[i].c_str(), value));
}
napi_value sendableObject = nullptr;
status = napi_create_sendable_object_with_properties(env, descriptors.size(), descriptors.data(), &sendableObject);
ASSERT(status == napi_ok, "napi_create_sendable_object_with_properties failed", nullptr);
return sendableObject;
}
napi_value JSUtils::ToSendableArray(napi_env env, napi_value jsValue)
{
LOG_DEBUG("jsArray -> sendableArray");
uint32_t arrLen = 0;
napi_status status = napi_get_array_length(env, jsValue, &arrLen);
ASSERT(status == napi_ok, "napi_get_array_length failed", nullptr);
napi_value sendableArray = nullptr;
status = napi_create_sendable_array_with_length(env, arrLen, &sendableArray);
ASSERT(status == napi_ok, "napi_create_sendable_array_with_length failed", nullptr);
for (size_t i = 0; i < arrLen; ++i) {
napi_value element;
status = napi_get_element(env, jsValue, i, &element);
ASSERT(status == napi_ok, "napi_get_element failed", nullptr);
status = napi_set_element(env, sendableArray, i, Convert2Sendable(env, element));
ASSERT(status == napi_ok, "napi_set_element failed", nullptr);
}
return sendableArray;
}
napi_value JSUtils::ToSendableTypedArray(napi_env env, napi_value jsValue)
{
LOG_DEBUG("jsTypedArryay -> sendableTypedArryay");
napi_typedarray_type type;
size_t length = 0;
void *tmp = nullptr;
napi_status status = napi_get_typedarray_info(env, jsValue, &type, &length, &tmp, nullptr, nullptr);
ASSERT(status == napi_ok, "napi_get_typedarray_info failed", nullptr);
if (type != napi_uint8_array && type != napi_float32_array) {
LOG_ERROR("type is invalid %{public}d", type);
return nullptr;
}
napi_value sendableTypedArryay = nullptr;
void *native = nullptr;
napi_value buffer = nullptr;
status = napi_create_sendable_arraybuffer(env, length, (void **)&native, &buffer);
ASSERT(status == napi_ok, "napi_create_sendable_arraybuffer failed", nullptr);
if (length > 0) {
errno_t result = memcpy_s(native, length, tmp, length);
if (result != EOK) {
LOG_ERROR("memcpy_s failed, result is %{public}d", result);
return nullptr;
}
}
auto size = (type == napi_uint8_array) ? length : length / sizeof(float);
status = napi_create_sendable_typedarray(env, type, size, buffer, 0, &sendableTypedArryay);
ASSERT(status == napi_ok, "napi_create_sendable_typedarray failed", nullptr);
return sendableTypedArryay;
}
napi_value JSUtils::Convert2Sendable(napi_env env, napi_value jsValue)
{
bool result = false;
napi_status status = napi_is_sendable(env, jsValue, &result);
ASSERT(status == napi_ok, "napi_is_sendable failed", nullptr);
if (result) {
return jsValue;
}
status = napi_is_array(env, jsValue, &result);
ASSERT(status == napi_ok, "napi_is_array failed", nullptr);
if (result) {
return ToSendableArray(env, jsValue);
}
status = napi_is_typedarray(env, jsValue, &result);
ASSERT(status == napi_ok, "napi_is_typedarray failed", nullptr);
if (result) {
return ToSendableTypedArray(env, jsValue);
}
return ToSendableObject(env, jsValue);
}
} // namespace AppDataMgrJsKit
} // namespace OHOS

View File

@ -13,18 +13,22 @@
* limitations under the License.
*/
#define LOG_TAG "JSUtils"
#include "js_utils.h"
#include <cstring>
#include "js_native_api_types.h"
#include "logger.h"
#include <cstring>
#include "securec.h"
using namespace OHOS::Rdb;
#define CHECK_RETURN_RET(assertion, message, revt) \
do { \
if (!(assertion)) { \
LOG_WARN("assertion (" #assertion ") failed: " message); \
return revt; \
} \
#define CHECK_RETURN_RET(assertion, message, revt) \
do { \
if (!(assertion)) { \
LOG_WARN("assertion (" #assertion ") failed: " message); \
return revt; \
} \
} while (0)
namespace OHOS {
@ -47,15 +51,15 @@ const std::optional<JSUtils::JsFeatureSpace> JSUtils::GetJsFeatureSpace(const st
[](const JsFeatureSpace &JsFeatureSpace1, const JsFeatureSpace &JsFeatureSpace2) {
return strcmp(JsFeatureSpace1.spaceName, JsFeatureSpace2.spaceName) < 0;
});
if (iter < FEATURE_NAME_SPACES + sizeof(FEATURE_NAME_SPACES) / sizeof(FEATURE_NAME_SPACES[0])
&& strcmp(iter->spaceName, name.data()) == 0) {
if (iter < FEATURE_NAME_SPACES + sizeof(FEATURE_NAME_SPACES) / sizeof(FEATURE_NAME_SPACES[0]) &&
strcmp(iter->spaceName, name.data()) == 0) {
return *iter;
}
return std::nullopt;
}
std::pair<napi_status, napi_value> JSUtils::GetInnerValue(
napi_env env, napi_value in, const std::string& prop, bool optional)
napi_env env, napi_value in, const std::string &prop, bool optional)
{
bool hasProp = false;
napi_status status = napi_has_named_property(env, in, prop.c_str(), &hasProp);
@ -202,8 +206,9 @@ int32_t JSUtils::Convert2Value(napi_env env, napi_value jsValue, std::vector<flo
return napi_invalid_arg;
}
output = (tmp != nullptr ? std::vector<float>(static_cast<float*>(tmp),
static_cast<float*>(tmp) + length / sizeof(float)) : std::vector<float>());
output = (tmp != nullptr
? std::vector<float>(static_cast<float *>(tmp), static_cast<float *>(tmp) + length / sizeof(float))
: std::vector<float>());
return status;
}
@ -257,8 +262,8 @@ int32_t JSUtils::Convert2Value(napi_env env, napi_value jsValue, std::vector<uin
return napi_invalid_arg;
}
output = (tmp != nullptr ? std::vector<uint8_t>(static_cast<uint8_t*>(tmp),
static_cast<uint8_t*>(tmp) + length) : std::vector<uint8_t>());
output = (tmp != nullptr ? std::vector<uint8_t>(static_cast<uint8_t *>(tmp), static_cast<uint8_t *>(tmp) + length)
: std::vector<uint8_t>());
return status;
}
@ -334,20 +339,6 @@ int32_t JSUtils::Convert2Value(napi_env env, napi_value jsValue, std::map<std::s
return napi_ok;
}
napi_value JSUtils::Convert2JSValue(napi_env env, const std::vector<std::string> &value)
{
napi_value jsValue = nullptr;
napi_status status = napi_create_array_with_length(env, value.size(), &jsValue);
if (status != napi_ok) {
return nullptr;
}
for (size_t i = 0; i < value.size(); ++i) {
napi_set_element(env, jsValue, i, Convert2JSValue(env, value[i]));
}
return jsValue;
}
napi_value JSUtils::Convert2JSValue(napi_env env, const std::string &value)
{
napi_value jsValue = nullptr;
@ -601,5 +592,112 @@ bool JSUtils::Equal(napi_env env, napi_ref ref, napi_value value)
napi_strict_equals(env, value, callback, &isEquals);
return isEquals;
}
napi_value JSUtils::ToJsObject(napi_env env, napi_value sendableValue)
{
LOG_DEBUG("sendableObject -> jsObject");
napi_value keys = nullptr;
napi_status status = napi_get_all_property_names(env, sendableValue, napi_key_own_only,
static_cast<napi_key_filter>(napi_key_enumerable | napi_key_skip_symbols), napi_key_numbers_to_strings, &keys);
ASSERT(status == napi_ok, "napi_get_all_property_names failed", nullptr);
uint32_t length = 0;
status = napi_get_array_length(env, keys, &length);
ASSERT(status == napi_ok, "napi_get_array_length failed", nullptr);
std::vector<napi_property_descriptor> descriptors;
// keysHold guarantees that the string address is valid before create the sendable object.
std::vector<std::string> keysHold(length, "");
for (uint32_t i = 0; i < length; ++i) {
napi_value key = nullptr;
status = napi_get_element(env, keys, i, &key);
ASSERT(status == napi_ok, "napi_get_element failed", nullptr);
JSUtils::Convert2Value(env, key, keysHold[i]);
napi_value value = nullptr;
status = napi_get_named_property(env, sendableValue, keysHold[i].c_str(), &value);
ASSERT(status == napi_ok, "napi_get_named_property failed", nullptr);
descriptors.emplace_back(DECLARE_JS_PROPERTY(env, keysHold[i].c_str(), value));
}
napi_value jsObject = nullptr;
status = napi_create_object_with_properties(env, &jsObject, descriptors.size(), descriptors.data());
ASSERT(status == napi_ok, "napi_create_object_with_properties failed", nullptr);
return jsObject;
}
napi_value JSUtils::ToJsArray(napi_env env, napi_value sendableValue)
{
LOG_DEBUG("sendableArray -> jsArray");
uint32_t arrLen = 0;
napi_status status = napi_get_array_length(env, sendableValue, &arrLen);
ASSERT(status == napi_ok, "napi_get_array_length failed", nullptr);
napi_value jsArray = nullptr;
status = napi_create_array_with_length(env, arrLen, &jsArray);
ASSERT(status == napi_ok, "napi_create_array_with_length failed", nullptr);
for (size_t i = 0; i < arrLen; ++i) {
napi_value element;
status = napi_get_element(env, sendableValue, i, &element);
ASSERT(status == napi_ok, "napi_get_element failed", nullptr);
status = napi_set_element(env, jsArray, i, Convert2JSValue(env, element));
ASSERT(status == napi_ok, "napi_set_element failed", nullptr);
}
return jsArray;
}
napi_value JSUtils::ToJsTypedArray(napi_env env, napi_value sendableValue)
{
LOG_DEBUG("sendableTypedArray -> jsTypedArray");
napi_typedarray_type type;
size_t length = 0;
void *tmp = nullptr;
napi_status status = napi_get_typedarray_info(env, sendableValue, &type, &length, &tmp, nullptr, nullptr);
ASSERT(status == napi_ok, "napi_get_typedarray_info failed", nullptr);
if (type != napi_uint8_array && type != napi_float32_array) {
LOG_ERROR("type is invalid %{public}d", type);
return nullptr;
}
napi_value jsTypedArray = nullptr;
void *native = nullptr;
napi_value buffer = nullptr;
status = napi_create_arraybuffer(env, length, (void **)&native, &buffer);
ASSERT(status == napi_ok, "napi_create_arraybuffer failed", nullptr);
if (length > 0) {
errno_t result = memcpy_s(native, length, tmp, length);
if (result != EOK) {
LOG_ERROR("memcpy_s failed, result is %{public}d", result);
return nullptr;
}
}
auto size = (type == napi_uint8_array) ? length : length / sizeof(float);
status = napi_create_typedarray(env, type, size, buffer, 0, &jsTypedArray);
ASSERT(status == napi_ok, "napi_create_typedarray failed", nullptr);
return jsTypedArray;
}
napi_value JSUtils::Convert2JSValue(napi_env env, napi_value sendableValue)
{
napi_valuetype type = napi_undefined;
napi_status status = napi_typeof(env, sendableValue, &type);
ASSERT(status == napi_ok, "napi_typeof failed", nullptr);
if (type != napi_object) {
return sendableValue;
}
bool result = false;
status = napi_is_sendable(env, sendableValue, &result);
ASSERT(status == napi_ok, "napi_is_sendable failed", nullptr);
if (!result) {
return sendableValue;
}
status = napi_is_array(env, sendableValue, &result);
ASSERT(status == napi_ok, "napi_is_array failed", nullptr);
if (result) {
return ToJsArray(env, sendableValue);
}
status = napi_is_typedarray(env, sendableValue, &result);
ASSERT(status == napi_ok, "napi_is_typedarray failed", nullptr);
if (result) {
return ToJsTypedArray(env, sendableValue);
}
return ToJsObject(env, sendableValue);
}
} // namespace AppDataMgrJsKit
} // namespace OHOS

View File

@ -61,6 +61,8 @@ if (is_ohos) {
sources += [
"${relational_store_js_common_path}/src/js_ability.cpp",
"${relational_store_js_common_path}/src/js_sendable_utils.cpp",
"src/napi_rdb_sendable_utils.cpp",
"src/napi_rdb_store_observer.cpp",
]

View File

@ -40,14 +40,6 @@ struct JsErrorCode {
};
const std::optional<JsErrorCode> GetJsErrorCode(int32_t errorCode);
#define ASSERT(condition, message, retVal) \
do { \
if (!(condition)) { \
LOG_ERROR("test (" #condition ") failed: " message); \
return retVal; \
} \
} while (0)
#define RDB_REVT_NOTHING
#define RDB_DO_NOTHING

View File

@ -17,7 +17,9 @@
#define RDB_JSKIT_NAPI_RDB_JS_UTILS_H
#include <stdint.h>
#include "asset_value.h"
#include "js_sendable_utils.h"
#include "js_utils.h"
#include "napi_rdb_error.h"
#include "napi_rdb_store_observer.h"
@ -88,11 +90,12 @@ template<>
napi_value Convert2JSValue(napi_env env, const ValueObject &value);
template<>
napi_value Convert2JSValue(napi_env env, const DistributedRdb::Statistic &statistic);
napi_value Convert2JSValue(napi_env env, const DistributedRdb::Statistic &value);
template<>
napi_value Convert2JSValue(napi_env env, const DistributedRdb::TableDetail &tableDetail);
napi_value Convert2JSValue(napi_env env, const DistributedRdb::TableDetail &value);
template<>
napi_value Convert2JSValue(napi_env env, const DistributedRdb::ProgressDetail &progressDetail);
napi_value Convert2JSValue(napi_env env, const DistributedRdb::ProgressDetail &value);
template<>
napi_value Convert2JSValue(napi_env env, const DistributedRdb::Details &details);
template<>
@ -106,7 +109,7 @@ int32_t Convert2Value(napi_env env, napi_value jsValue, BigInt &value);
template<>
std::string ToString(const PRIKey &key);
template<>
napi_value Convert2JSValue(napi_env env, const SqlExecInfo &sqlExeInfo);
napi_value Convert2JSValue(napi_env env, const SqlExecInfo &value);
bool IsNapiString(napi_env env, napi_value value);
std::tuple<int32_t, std::shared_ptr<Error>> GetRealPath(

View File

@ -0,0 +1,35 @@
/*
* Copyright (c) 2023 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef RDB_JSKIT_NAPI_RDB_SENDABLE_UTILS_H
#define RDB_JSKIT_NAPI_RDB_SENDABLE_UTILS_H
#include "napi_rdb_js_utils.h"
namespace OHOS::AppDataMgrJsKit {
namespace JSUtils {
template<>
napi_value Convert2Sendable(napi_env env, const Asset &value);
template<>
napi_value Convert2Sendable(napi_env env, const RowEntity &rowEntity);
template<>
napi_value Convert2Sendable(napi_env env, const ValueObject &value);
template<>
napi_value Convert2Sendable(napi_env env, const BigInt &value);
} // namespace JSUtils
} // namespace OHOS::AppDataMgrJsKit
#endif // RDB_JSKIT_NAPI_RDB_SENDABLE_UTILS_H

View File

@ -75,6 +75,7 @@ private:
static napi_value GetDouble(napi_env env, napi_callback_info info);
static napi_value IsColumnNull(napi_env env, napi_callback_info info);
static napi_value GetRow(napi_env env, napi_callback_info info);
static napi_value GetSendableRow(napi_env env, napi_callback_info info);
static napi_value GetValue(napi_env env, napi_callback_info info);
static napi_value IsClosed(napi_env env, napi_callback_info info);
};

View File

@ -72,6 +72,7 @@ private:
static napi_value GetDouble(napi_env env, napi_callback_info info);
static napi_value IsColumnNull(napi_env env, napi_callback_info info);
static napi_value GetRow(napi_env env, napi_callback_info info);
static napi_value GetSendableRow(napi_env env, napi_callback_info info);
static napi_value GetValue(napi_env env, napi_callback_info info);
static napi_value IsClosed(napi_env env, napi_callback_info info);

View File

@ -22,8 +22,8 @@
#include "js_native_api_types.h"
#include "logger.h"
#include "rdb_errno.h"
#include "rdb_sql_utils.h"
#include "rdb_sql_statistic.h"
#include "rdb_sql_utils.h"
#include "rdb_types.h"
#include "result_set.h"
@ -113,91 +113,104 @@ int32_t Convert2Value(napi_env env, napi_value jsValue, ValueObject &valueObject
template<>
napi_value Convert2JSValue(napi_env env, const Asset &value)
{
napi_value object = nullptr;
NAPI_CALL_RETURN_ERR(napi_create_object(env, &object), object);
NAPI_CALL_RETURN_ERR(SetNamedProperty(env, object, "name", value.name), object);
NAPI_CALL_RETURN_ERR(SetNamedProperty(env, object, "uri", value.uri), object);
NAPI_CALL_RETURN_ERR(SetNamedProperty(env, object, "createTime", value.createTime), object);
NAPI_CALL_RETURN_ERR(SetNamedProperty(env, object, "modifyTime", value.modifyTime), object);
NAPI_CALL_RETURN_ERR(SetNamedProperty(env, object, "size", value.size), object);
NAPI_CALL_RETURN_ERR(SetNamedProperty(env, object, "path", value.path), object);
auto outputStatus = value.status & ~0xF0000000;
NAPI_CALL_RETURN_ERR(SetNamedProperty(env, object, "status", outputStatus), object);
std::vector<napi_property_descriptor> descriptors = {
DECLARE_JS_PROPERTY(env, "name", value.name),
DECLARE_JS_PROPERTY(env, "uri", value.uri),
DECLARE_JS_PROPERTY(env, "createTime", value.createTime),
DECLARE_JS_PROPERTY(env, "modifyTime", value.modifyTime),
DECLARE_JS_PROPERTY(env, "size", value.size),
DECLARE_JS_PROPERTY(env, "path", value.path),
DECLARE_JS_PROPERTY(env, "status", outputStatus),
};
napi_value object = nullptr;
NAPI_CALL_RETURN_ERR(
napi_create_object_with_properties(env, &object, descriptors.size(), descriptors.data()), object);
return object;
}
template<>
napi_value Convert2JSValue(napi_env env, const RowEntity &rowEntity)
{
napi_value object = nullptr;
NAPI_CALL_RETURN_ERR(napi_create_object(env, &object), object);
std::vector<napi_property_descriptor> descriptors;
auto &values = rowEntity.Get();
for (auto const &[key, value] : values) {
NAPI_CALL_RETURN_ERR(SetNamedProperty(env, object, key.c_str(), value), object);
descriptors.emplace_back(DECLARE_JS_PROPERTY(env, key.c_str(), value));
}
napi_value object = nullptr;
NAPI_CALL_RETURN_ERR(
napi_create_object_with_properties(env, &object, descriptors.size(), descriptors.data()), object);
return object;
}
template<>
napi_value Convert2JSValue(napi_env env, const ValueObject &valueObject)
napi_value Convert2JSValue(napi_env env, const ValueObject &value)
{
return JSUtils::Convert2JSValue(env, valueObject.value);
return Convert2JSValue(env, value.value);
}
template<>
napi_value Convert2JSValue(napi_env env, const DistributedRdb::Statistic &statistic)
napi_value Convert2JSValue(napi_env env, const DistributedRdb::Statistic &value)
{
napi_value object = nullptr;
NAPI_CALL_RETURN_ERR(napi_create_object(env, &object), object);
std::vector<napi_property_descriptor> descriptors = {
DECLARE_JS_PROPERTY(env, "total", value.total),
DECLARE_JS_PROPERTY(env, "success", value.success),
DECLARE_JS_PROPERTY(env, "successful", value.success),
DECLARE_JS_PROPERTY(env, "failed", value.failed),
DECLARE_JS_PROPERTY(env, "remained", value.untreated),
};
NAPI_CALL_RETURN_ERR(SetNamedProperty(env, object, "total", statistic.total), object);
NAPI_CALL_RETURN_ERR(SetNamedProperty(env, object, "success", statistic.success), object);
NAPI_CALL_RETURN_ERR(SetNamedProperty(env, object, "successful", statistic.success), object);
NAPI_CALL_RETURN_ERR(SetNamedProperty(env, object, "failed", statistic.failed), object);
NAPI_CALL_RETURN_ERR(SetNamedProperty(env, object, "remained", statistic.untreated), object);
napi_value object = nullptr;
NAPI_CALL_RETURN_ERR(
napi_create_object_with_properties(env, &object, descriptors.size(), descriptors.data()), object);
return object;
}
template<>
napi_value Convert2JSValue(napi_env env, const DistributedRdb::TableDetail &tableDetail)
napi_value Convert2JSValue(napi_env env, const DistributedRdb::TableDetail &value)
{
std::vector<napi_property_descriptor> descriptors = {
DECLARE_JS_PROPERTY(env, "upload", value.upload),
DECLARE_JS_PROPERTY(env, "download", value.download),
};
napi_value object = nullptr;
NAPI_CALL_RETURN_ERR(napi_create_object(env, &object), object);
NAPI_CALL_RETURN_ERR(SetNamedProperty(env, object, "upload", tableDetail.upload), object);
NAPI_CALL_RETURN_ERR(SetNamedProperty(env, object, "download", tableDetail.download), object);
NAPI_CALL_RETURN_ERR(
napi_create_object_with_properties(env, &object, descriptors.size(), descriptors.data()), object);
return object;
}
template<>
napi_value Convert2JSValue(napi_env env, const DistributedRdb::ProgressDetail &progressDetail)
napi_value Convert2JSValue(napi_env env, const DistributedRdb::ProgressDetail &value)
{
napi_value object = nullptr;
NAPI_CALL_RETURN_ERR(napi_create_object(env, &object), object);
std::vector<napi_property_descriptor> descriptors = {
DECLARE_JS_PROPERTY(env, "schedule", value.progress),
DECLARE_JS_PROPERTY(env, "code", value.code),
DECLARE_JS_PROPERTY(env, "details", value.details),
};
napi_value schedule = Convert2JSValue(env, progressDetail.progress);
napi_value code = Convert2JSValue(env, progressDetail.code);
napi_value details = Convert2JSValue(env, progressDetail.details);
if (details == nullptr) {
return nullptr;
}
napi_set_named_property(env, object, "schedule", schedule);
napi_set_named_property(env, object, "code", code);
napi_set_named_property(env, object, "details", details);
napi_value object = nullptr;
NAPI_CALL_RETURN_ERR(
napi_create_object_with_properties(env, &object, descriptors.size(), descriptors.data()), object);
return object;
}
template<>
napi_value Convert2JSValue(napi_env env, const DistributedRdb::SqlObserver::SqlExecutionInfo &sqlExeInfo)
napi_value Convert2JSValue(napi_env env, const DistributedRdb::SqlObserver::SqlExecutionInfo &value)
{
napi_value object = nullptr;
NAPI_CALL_RETURN_ERR(napi_create_object(env, &object), object);
std::vector<napi_property_descriptor> descriptors = {
DECLARE_JS_PROPERTY(env, "sql", value.sql_),
DECLARE_JS_PROPERTY(env, "totalTime", value.totalTime_),
DECLARE_JS_PROPERTY(env, "waitTime", value.waitTime_),
DECLARE_JS_PROPERTY(env, "prepareTime", value.prepareTime_),
DECLARE_JS_PROPERTY(env, "executeTime", value.executeTime_),
};
std::vector<std::string> sql(sqlExeInfo.sql_.begin(), sqlExeInfo.sql_.end());
NAPI_CALL_RETURN_ERR(SetNamedProperty(env, object, "sql", sql), object);
NAPI_CALL_RETURN_ERR(SetNamedProperty(env, object, "totalTime", sqlExeInfo.totalTime_), object);
NAPI_CALL_RETURN_ERR(SetNamedProperty(env, object, "waitTime", sqlExeInfo.waitTime_), object);
NAPI_CALL_RETURN_ERR(SetNamedProperty(env, object, "prepareTime", sqlExeInfo.prepareTime_), object);
NAPI_CALL_RETURN_ERR(SetNamedProperty(env, object, "executeTime", sqlExeInfo.executeTime_), object);
napi_value object = nullptr;
NAPI_CALL_RETURN_ERR(
napi_create_object_with_properties(env, &object, descriptors.size(), descriptors.data()), object);
return object;
}
@ -210,13 +223,17 @@ napi_value Convert2JSValue(napi_env env, const DistributedRdb::Details &details)
template<>
napi_value Convert2JSValue(napi_env env, const JSChangeInfo &value)
{
std::vector<napi_property_descriptor> descriptors = {
DECLARE_JS_PROPERTY(env, "table", value.table),
DECLARE_JS_PROPERTY(env, "type", value.type),
DECLARE_JS_PROPERTY(env, "inserted", value.inserted),
DECLARE_JS_PROPERTY(env, "updated", value.updated),
DECLARE_JS_PROPERTY(env, "deleted", value.deleted),
};
napi_value object = nullptr;
NAPI_CALL_RETURN_ERR(napi_create_object(env, &object), object);
NAPI_CALL_RETURN_ERR(SetNamedProperty(env, object, "table", value.table), object);
NAPI_CALL_RETURN_ERR(SetNamedProperty(env, object, "type", value.type), object);
NAPI_CALL_RETURN_ERR(SetNamedProperty(env, object, "inserted", value.inserted), object);
NAPI_CALL_RETURN_ERR(SetNamedProperty(env, object, "updated", value.updated), object);
NAPI_CALL_RETURN_ERR(SetNamedProperty(env, object, "deleted", value.deleted), object);
NAPI_CALL_RETURN_ERR(
napi_create_object_with_properties(env, &object, descriptors.size(), descriptors.data()), object);
return object;
}
@ -228,7 +245,7 @@ napi_value Convert2JSValue(napi_env env, const Date &date)
return jsDeta;
}
template<>
napi_value Convert2JSValue(napi_env env, const BigInt& value)
napi_value Convert2JSValue(napi_env env, const BigInt &value)
{
napi_value val = nullptr;
napi_status status = napi_create_bigint_words(env, value.Sign(), value.Size(), value.TrueForm(), &val);
@ -239,7 +256,7 @@ napi_value Convert2JSValue(napi_env env, const BigInt& value)
}
template<>
int32_t Convert2Value(napi_env env, napi_value jsValue, BigInt& value)
int32_t Convert2Value(napi_env env, napi_value jsValue, BigInt &value)
{
napi_valuetype type = napi_undefined;
napi_status status = napi_typeof(env, jsValue, &type);
@ -403,7 +420,8 @@ std::tuple<int32_t, std::shared_ptr<Error>> GetRealPath(
std::make_tuple(ERR, std::make_shared<ParamError>("customDir", "a relative directory.")));
// customDir length is limited to 128 bytes
CHECK_RETURN_CORE(rdbConfig.customDir.length() <= 128, RDB_DO_NOTHING,
std::make_tuple(ERR, std::make_shared<ParamError>("customDir length", "less than or equal to 128 bytes.")));
std::make_tuple(ERR, std::make_shared<ParamError>("customDir length", "less than or equal to 128 "
"bytes.")));
}
std::string baseDir = param.baseDir;

View File

@ -0,0 +1,72 @@
/*
* Copyright (c) 2023 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define LOG_TAG "NapiRdbSendableUtils"
#include "napi_rdb_sendable_utils.h"
#define NAPI_CALL_RETURN_ERR(theCall, retVal) \
do { \
if ((theCall) != napi_ok) { \
return retVal; \
} \
} while (0)
namespace OHOS::AppDataMgrJsKit {
namespace JSUtils {
template<>
napi_value Convert2Sendable(napi_env env, const Asset &value)
{
auto outputStatus = value.status & ~0xF0000000;
std::vector<napi_property_descriptor> descriptors = {
DECLARE_SENDABLE_PROPERTY(env, "name", value.name),
DECLARE_SENDABLE_PROPERTY(env, "uri", value.uri),
DECLARE_SENDABLE_PROPERTY(env, "createTime", value.createTime),
DECLARE_SENDABLE_PROPERTY(env, "modifyTime", value.modifyTime),
DECLARE_SENDABLE_PROPERTY(env, "size", value.size),
DECLARE_SENDABLE_PROPERTY(env, "path", value.path),
DECLARE_SENDABLE_PROPERTY(env, "status", outputStatus),
};
napi_value object = nullptr;
NAPI_CALL_RETURN_ERR(
napi_create_sendable_object_with_properties(env, descriptors.size(), descriptors.data(), &object), object);
return object;
}
template<>
napi_value Convert2Sendable(napi_env env, const RowEntity &rowEntity)
{
napi_value map = nullptr;
NAPI_CALL_RETURN_ERR(napi_create_sendable_map(env, &map), nullptr);
auto &values = rowEntity.Get();
for (auto const &[key, value] : values) {
NAPI_CALL_RETURN_ERR(napi_map_set_named_property(env, map, key.c_str(), Convert2Sendable(env, value)), nullptr);
}
return map;
}
template<>
napi_value Convert2Sendable(napi_env env, const ValueObject &value)
{
return Convert2Sendable(env, value.value);
}
template<>
napi_value Convert2Sendable(napi_env env, const BigInt &value)
{
return Convert2JSValue(env, value);
}
}; // namespace JSUtils
} // namespace OHOS::AppDataMgrJsKit

View File

@ -12,14 +12,17 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define LOG_TAG "NapiRdbStore"
#include "napi_rdb_store.h"
#include <algorithm>
#include <cinttypes>
#include <cstdint>
#include <string>
#include <vector>
#include "js_native_api.h"
#include "js_native_api_types.h"
#include "js_utils.h"
#include "logger.h"
@ -60,6 +63,8 @@ struct PredicatesProxy {
std::shared_ptr<DataShareAbsPredicates> predicates_;
};
#endif
constexpr int32_t KEY_INDEX = 0;
constexpr int32_t VALUE_INDEX = 1;
struct RdbStoreContext : public ContextBase {
std::string device;
std::string tableName;
@ -535,14 +540,55 @@ int ParseTxId(const napi_env env, const napi_value arg, std::shared_ptr<RdbStore
return OK;
}
int ParseSendableValuesBucket(const napi_env env, const napi_value map, std::shared_ptr<RdbStoreContext> context)
{
uint32_t length = 0;
napi_status status = napi_map_get_size(env, map, &length);
auto error = std::make_shared<ParamError>("ValuesBucket is invalid.");
CHECK_RETURN_SET(status == napi_ok && length > 0, error);
napi_value entries = nullptr;
status = napi_map_get_entries(env, map, &entries);
CHECK_RETURN_SET(status == napi_ok, std::make_shared<InnerError>("napi_map_get_entries failed."));
for (uint32_t i = 0; i < length; ++i) {
napi_value iter = nullptr;
status = napi_map_iterator_get_next(env, entries, &iter);
CHECK_RETURN_SET(status == napi_ok, std::make_shared<InnerError>("napi_map_iterator_get_next failed."));
napi_value values = nullptr;
status = napi_get_named_property(env, iter, "value", &values);
CHECK_RETURN_SET(status == napi_ok, std::make_shared<InnerError>("napi_get_named_property value failed."));
napi_value key = nullptr;
status = napi_get_element(env, values, KEY_INDEX, &key);
CHECK_RETURN_SET(status == napi_ok, std::make_shared<InnerError>("napi_get_element key failed."));
std::string keyStr = JSUtils::Convert2String(env, key);
napi_value value = nullptr;
status = napi_get_element(env, values, VALUE_INDEX, &value);
CHECK_RETURN_SET(status == napi_ok, std::make_shared<InnerError>("napi_get_element value failed."));
ValueObject valueObject;
int32_t ret = JSUtils::Convert2Value(env, value, valueObject.value);
if (ret == napi_ok) {
context->valuesBucket.Put(keyStr, valueObject);
} else if (ret != napi_generic_failure) {
CHECK_RETURN_SET(false, std::make_shared<ParamError>("The value type of " + keyStr, "invalid."));
}
}
return OK;
}
int ParseValuesBucket(const napi_env env, const napi_value arg, std::shared_ptr<RdbStoreContext> context)
{
bool isMap = false;
napi_status status = napi_is_map(env, arg, &isMap);
CHECK_RETURN_SET(
status == napi_ok, std::make_shared<InnerError>("call napi_is_map failed" + std::to_string(status)));
if (isMap) {
return ParseSendableValuesBucket(env, arg, context);
}
napi_value keys = nullptr;
napi_get_all_property_names(env, arg, napi_key_own_only,
static_cast<napi_key_filter>(napi_key_enumerable | napi_key_skip_symbols),
napi_key_numbers_to_strings, &keys);
uint32_t arrLen = 0;
napi_status status = napi_get_array_length(env, keys, &arrLen);
status = napi_get_array_length(env, keys, &arrLen);
CHECK_RETURN_SET(status == napi_ok && arrLen > 0, std::make_shared<ParamError>("ValuesBucket is invalid"));
for (size_t i = 0; i < arrLen; ++i) {

View File

@ -20,8 +20,8 @@
#include "js_utils.h"
#include "logger.h"
#include "napi_rdb_error.h"
#include "napi_rdb_js_utils.h"
#include "napi_rdb_trace.h"
#if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM)
#include "rdb_result_set_bridge.h"
#include "string_ex.h"
@ -556,6 +556,18 @@ napi_value ResultSetProxy::GetRow(napi_env env, napi_callback_info info)
return JSUtils::Convert2JSValue(env, rowEntity);
}
napi_value ResultSetProxy::GetSendableRow(napi_env env, napi_callback_info info)
{
DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__));
ResultSetProxy *resultSetProxy = GetInnerResultSet(env, info);
CHECK_RETURN_NULL(resultSetProxy && resultSetProxy->GetInstance());
RowEntity rowEntity;
int errCode = resultSetProxy->GetInstance()->GetRow(rowEntity);
RDB_NAPI_ASSERT(env, errCode == E_OK, std::make_shared<InnerError>(errCode));
return JSUtils::Convert2Sendable(env, rowEntity);
}
napi_value ResultSetProxy::GetValue(napi_env env, napi_callback_info info)
{
DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__));
@ -604,6 +616,7 @@ void ResultSetProxy::Init(napi_env env, napi_value exports)
DECLARE_NAPI_FUNCTION("isColumnNull", IsColumnNull),
DECLARE_NAPI_FUNCTION("getValue", GetValue),
DECLARE_NAPI_FUNCTION("getRow", GetRow),
DECLARE_NAPI_FUNCTION("getSendableRow", GetSendableRow),
DECLARE_NAPI_GETTER("columnNames", GetAllColumnNames),
DECLARE_NAPI_GETTER("columnCount", GetColumnCount),

View File

@ -0,0 +1,68 @@
# Copyright (c) 2022 Huawei Device Co., Ltd.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import("//build/ohos.gni")
import("//foundation/distributeddatamgr/relational_store/relational_store.gni")
ohos_copy("relational_store_declaration") {
sources = [ "./api" ]
outputs = [ target_out_dir + "/$target_name/" ]
module_source_dir = target_out_dir + "/$target_name"
module_install_name = ""
subsystem_name = "distributeddatamgr"
part_name = "relational_store"
}
ohos_shared_library("sendablerelationalstore") {
branch_protector_ret = "pac_ret"
sanitize = {
boundary_sanitize = true
ubsan = true
cfi = true
cfi_cross_dso = true
debug = false
}
include_dirs = [
"${relational_store_common_path}/include",
"${relational_store_js_common_path}/include",
"${relational_store_napi_path}/relationalstore/include",
"include",
]
sources = [
"${relational_store_js_common_path}/src/js_ability.cpp",
"${relational_store_js_common_path}/src/js_sendable_utils.cpp",
"${relational_store_js_common_path}/src/js_utils.cpp",
"${relational_store_napi_path}/relationalstore/src/napi_rdb_error.cpp",
"${relational_store_napi_path}/relationalstore/src/napi_rdb_js_utils.cpp",
"${relational_store_napi_path}/relationalstore/src/napi_rdb_sendable_utils.cpp",
"src/entry_point.cpp",
"src/napi_rdb_store_convert_utils.cpp",
]
defines = [ "SQLITE_DISTRIBUTE_RELATIONAL" ]
deps = [ "${relational_store_innerapi_path}/rdb:native_rdb" ]
external_deps = [
"ability_runtime:abilitykit_native",
"ability_runtime:napi_base_context",
"hilog:libhilog",
"hitrace:hitrace_meter",
"napi:ace_napi",
]
subsystem_name = "distributeddatamgr"
part_name = "relational_store"
relative_install_dir = "module/data"
}

View File

@ -0,0 +1,29 @@
/*
* Copyright (c) 2024 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef RDB_JSKIT_NAPI_RDB_STORE_CONVERT_UTILS_H
#define RDB_JSKIT_NAPI_RDB_STORE_CONVERT_UTILS_H
#include "napi/native_api.h"
#include "napi/native_common.h"
#include "napi/native_node_api.h"
namespace OHOS {
namespace SendableRdb {
napi_value InitRdbStoreUtils(napi_env env, napi_value info);
} // namespace SendableRdb
} // namespace OHOS
#endif

View File

@ -0,0 +1,51 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "napi_rdb_store_convert_utils.h"
#include "napi/native_api.h"
using namespace OHOS::SendableRdb;
EXTERN_C_START
/*
* function for module exports
*/
static napi_value Init(napi_env env, napi_value exports)
{
InitRdbStoreUtils(env, exports);
return exports;
}
EXTERN_C_END
/*
* Module define
*/
static napi_module _module = {
.nm_version = 1,
.nm_flags = 0,
.nm_filename = nullptr,
.nm_register_func = Init,
.nm_modname = "data.sendableRelationalStore",
.nm_priv = ((void *)0),
.reserved = { 0 }
};
/*
* Module register function
*/
static __attribute__((constructor)) void RegisterModule(void)
{
napi_module_register(&_module);
}

View File

@ -0,0 +1,157 @@
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define LOG_TAG "NapiRdbStoreConvertUtils"
#include "napi_rdb_store_convert_utils.h"
#include "js_native_api.h"
#include "js_native_api_types.h"
#include "js_sendable_utils.h"
#include "js_utils.h"
#include "logger.h"
#include "napi_rdb_error.h"
#include "napi_rdb_js_utils.h"
#include "napi_rdb_sendable_utils.h"
using namespace OHOS::RelationalStoreJsKit;
using namespace OHOS::AppDataMgrJsKit::JSUtils;
namespace OHOS {
namespace SendableRdb {
constexpr int32_t KEY_INDEX = 0;
constexpr int32_t VALUE_INDEX = 1;
napi_value FromSendableValuesBucket(napi_env env, napi_callback_info info)
{
size_t argc = 1;
napi_value args[1] = { nullptr };
napi_status status = napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
RDB_NAPI_ASSERT(env, status == napi_ok && argc == 1, std::make_shared<ParamNumError>("1"));
bool isMap = false;
status = napi_is_map(env, args[0], &isMap);
RDB_NAPI_ASSERT(env, status == napi_ok && isMap,
std::make_shared<ParamError>("ValuesBucket is invalid" + std::to_string(status)));
uint32_t length = 0;
status = napi_map_get_size(env, args[0], &length);
RDB_NAPI_ASSERT(env, status == napi_ok, std::make_shared<InnerError>("napi_map_get_size failed."));
napi_value entries = nullptr;
status = napi_map_get_entries(env, args[0], &entries);
RDB_NAPI_ASSERT(env, status == napi_ok, std::make_shared<InnerError>("napi_map_get_entries failed."));
napi_value object = nullptr;
status = napi_create_object(env, &object);
for (uint32_t i = 0; i < length; ++i) {
napi_value iter = nullptr;
status = napi_map_iterator_get_next(env, entries, &iter);
RDB_NAPI_ASSERT(env, status == napi_ok, std::make_shared<InnerError>("napi_map_iterator_get_next failed."));
napi_value values = nullptr;
status = napi_get_named_property(env, iter, "value", &values);
RDB_NAPI_ASSERT(env, status == napi_ok, std::make_shared<InnerError>("napi_get_named_property value failed."));
napi_value key = nullptr;
status = napi_get_element(env, values, KEY_INDEX, &key);
RDB_NAPI_ASSERT(env, status == napi_ok, std::make_shared<InnerError>("napi_get_element key failed."));
napi_value value = nullptr;
status = napi_get_element(env, values, VALUE_INDEX, &value);
RDB_NAPI_ASSERT(env, status == napi_ok, std::make_shared<InnerError>("napi_get_element value failed."));
status = napi_set_property(env, object, key, Convert2JSValue(env, value));
RDB_NAPI_ASSERT(env, status == napi_ok, std::make_shared<InnerError>("napi_set_property failed."));
}
return object;
}
napi_value ToSendableValuesBucket(napi_env env, napi_callback_info info)
{
size_t argc = 1;
napi_value args[1] = { nullptr };
napi_status status = napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
RDB_NAPI_ASSERT(env, status == napi_ok && argc == 1, std::make_shared<ParamNumError>("1"));
napi_valuetype type = napi_undefined;
status = napi_typeof(env, args[0], &type);
RDB_NAPI_ASSERT(env, status == napi_ok && type == napi_object,
std::make_shared<ParamError>("ValuesBucket is invalid" + std::to_string(status)));
napi_value keys = nullptr;
napi_get_all_property_names(env, args[0], napi_key_own_only,
static_cast<napi_key_filter>(napi_key_enumerable | napi_key_skip_symbols), napi_key_numbers_to_strings, &keys);
uint32_t length = 0;
status = napi_get_array_length(env, keys, &length);
RDB_NAPI_ASSERT(env, status == napi_ok, std::make_shared<InnerError>("napi_get_array_length failed."));
napi_value map = nullptr;
status = napi_create_sendable_map(env, &map);
RDB_NAPI_ASSERT(env, status == napi_ok, std::make_shared<InnerError>("napi_create_sendable_map failed."));
for (uint32_t i = 0; i < length; ++i) {
napi_value key = nullptr;
status = napi_get_element(env, keys, i, &key);
RDB_NAPI_ASSERT(env, status == napi_ok, std::make_shared<InnerError>("napi_get_element failed."));
napi_value value = nullptr;
status = napi_get_property(env, args[0], key, &value);
RDB_NAPI_ASSERT(env, status == napi_ok, std::make_shared<InnerError>("napi_get_property failed."));
status = napi_map_set_property(env, map, key, Convert2Sendable(env, value));
RDB_NAPI_ASSERT(env, status == napi_ok, std::make_shared<InnerError>("napi_map_set_property failed."));
}
return map;
}
napi_value FromSendableAsset(napi_env env, napi_callback_info info)
{
size_t argc = 1;
napi_value args[1] = { nullptr };
napi_status status = napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
RDB_NAPI_ASSERT(env, status == napi_ok && argc == 1, std::make_shared<ParamNumError>("1"));
napi_valuetype type = napi_undefined;
status = napi_typeof(env, args[0], &type);
RDB_NAPI_ASSERT(env, status == napi_ok && type == napi_object,
std::make_shared<ParamError>("Asset is invalid" + std::to_string(status)));
return Convert2JSValue(env, args[0]);
}
napi_value ToSendableAsset(napi_env env, napi_callback_info info)
{
size_t argc = 1;
napi_value args[1] = { nullptr };
napi_status status = napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
RDB_NAPI_ASSERT(env, status == napi_ok && argc == 1, std::make_shared<ParamNumError>("1"));
napi_valuetype type = napi_undefined;
status = napi_typeof(env, args[0], &type);
RDB_NAPI_ASSERT(env, status == napi_ok && type == napi_object,
std::make_shared<ParamError>("Asset is invalid" + std::to_string(status)));
return Convert2Sendable(env, args[0]);
}
napi_value InitRdbStoreUtils(napi_env env, napi_value exports)
{
napi_property_descriptor properties[] = {
DECLARE_NAPI_FUNCTION("fromSendableValuesBucket", FromSendableValuesBucket),
DECLARE_NAPI_FUNCTION("toSendableValuesBucket", ToSendableValuesBucket),
DECLARE_NAPI_FUNCTION("fromSendableAsset", FromSendableAsset),
DECLARE_NAPI_FUNCTION("toSendableAsset", ToSendableAsset),
};
NAPI_CALL(env, napi_define_properties(env, exports, sizeof(properties) / sizeof(*properties), properties));
return exports;
}
} // namespace SendableRdb
} // namespace OHOS

View File

@ -19,11 +19,13 @@
#include <chrono>
#include <memory>
#include "concurrent_map.h"
#include "rdb_types.h"
#include "rdb_visibility.h"
namespace OHOS::DistributedRdb {
namespace OHOS {
template<typename _Key, typename _Tp>
class ConcurrentMap;
namespace DistributedRdb {
class SqlStatistic {
public:
enum Step : int32_t {
@ -54,4 +56,5 @@ private:
std::shared_ptr<SqlExecInfo> execInfo_;
};
}
}
#endif // OHOS_DISTRIBUTED_DATA_RELATIONAL_STORE_FRAMEWORKS_NATIVE_RDB_SQL_STATISTIC_H

View File

@ -150,7 +150,6 @@ int AbsSharedResultSet::Get(int32_t col, ValueObject& value)
LOG_ERROR("cellUnit is null, col is %{public}d!", col);
return E_ERROR;
}
switch (cellUnit->type) {
case AppDataFwk::SharedBlock::CELL_UNIT_TYPE_NULL:
break;

View File

@ -138,7 +138,13 @@ size_t RawDataParser::ParserRawData(const uint8_t* data, size_t length, BigInteg
if (sizeof(BIG_INT) > length - used) {
return 0;
}
auto magic = Endian::LeToH(*(reinterpret_cast<decltype(&BIG_INT)>(data)));
std::vector<uint8_t> copiedData;
const uint8_t *alignData = data;
if ((reinterpret_cast<uintptr_t>(data) & (sizeof(uintptr_t) - 1)) != 0) {
copiedData.assign(data, data + length);
alignData = copiedData.data();
}
auto magic = Endian::LeToH(*(reinterpret_cast<decltype(&BIG_INT)>(alignData)));
used += sizeof(BIG_INT);
if (magic != BIG_INT) {
return 0;
@ -147,19 +153,20 @@ size_t RawDataParser::ParserRawData(const uint8_t* data, size_t length, BigInteg
if (sizeof(uint32_t) > length - used) {
return 0;
}
uint32_t sign = Endian::LeToH(*(reinterpret_cast<const uint32_t *>(data + used)));
uint32_t sign = Endian::LeToH(*(reinterpret_cast<const uint32_t *>(alignData + used)));
used += sizeof(uint32_t);
if (sizeof(uint64_t) > length - used) {
return 0;
}
uint64_t count = Endian::LeToH(*(reinterpret_cast<const uint64_t *>(data + used)));
uint64_t count = Endian::LeToH(*(reinterpret_cast<const uint64_t *>(alignData + used)));
used += sizeof(uint64_t);
if (sizeof(uint64_t) * count > length - used) {
return 0;
}
const uint64_t *temp = (reinterpret_cast<const uint64_t *>(data + used));
const uint64_t *temp = (reinterpret_cast<const uint64_t *>(alignData + used));
std::vector<uint64_t> trueFrom(temp, temp + count);
used += sizeof(uint64_t) * count;
for (size_t i = 0; i < trueFrom.size(); ++i) {
@ -175,7 +182,13 @@ size_t RawDataParser::ParserRawData(const uint8_t* data, size_t length, RawDataP
if (sizeof(FLOUT32_ARRAY) > length - used) {
return 0;
}
auto magic = Endian::LeToH(*(reinterpret_cast<decltype(&FLOUT32_ARRAY)>(data)));
std::vector<uint8_t> copiedData;
const uint8_t *alignData = data;
if ((reinterpret_cast<uintptr_t>(data) & (sizeof(uintptr_t) - 1)) != 0) {
copiedData.assign(data, data + length);
alignData = copiedData.data();
}
auto magic = Endian::LeToH(*(reinterpret_cast<decltype(&FLOUT32_ARRAY)>(alignData)));
used += sizeof(FLOUT32_ARRAY);
if (magic != FLOUT32_ARRAY) {
return 0;
@ -185,13 +198,13 @@ size_t RawDataParser::ParserRawData(const uint8_t* data, size_t length, RawDataP
return 0;
}
uint32_t count = Endian::LeToH(*(reinterpret_cast<const uint32_t *>(data + used)));
uint32_t count = Endian::LeToH(*(reinterpret_cast<const uint32_t *>(alignData + used)));
used += sizeof(uint32_t);
if (sizeof(float) * count > length - used) {
return 0;
}
auto values = reinterpret_cast<const float *>(data + used);
auto values = reinterpret_cast<const float *>(alignData + used);
floats.assign(values, values + count);
used += sizeof(float) * count;
return used;

View File

@ -16,12 +16,14 @@
#define LOG_TAG "RdbSqlStatistic"
#include "rdb_sql_statistic.h"
#include "task_executor.h"
#include "rdb_errno.h"
#include "rdb_platform.h"
#include "logger.h"
#include <thread>
#include "concurrent_map.h"
#include "logger.h"
#include "rdb_errno.h"
#include "rdb_platform.h"
#include "task_executor.h"
namespace OHOS::DistributedRdb {
using namespace OHOS::Rdb;
using namespace OHOS::NativeRdb;

View File

@ -77,6 +77,7 @@ ohos_unittest("NativeRdbTest") {
"unittest/cache_result_set_test.cpp",
"unittest/common.cpp",
"unittest/connection_test.cpp",
"unittest/raw_data_parser_test.cpp",
"unittest/rd_utils_test.cpp",
"unittest/rdb_attach_test.cpp",
"unittest/rdb_bigint_test.cpp",

View File

@ -0,0 +1,150 @@
/*
* Copyright (c) 2024 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define LOG_TAG "RdbBigIntTest"
#include "raw_data_parser.h"
#include <gtest/gtest.h>
#include "value_object.h"
using namespace testing::ext;
using namespace OHOS::NativeRdb;
namespace Test {
class RawDataParserTest : public testing::Test {
public:
static void SetUpTestCase(void);
static void TearDownTestCase(void);
void SetUp();
void TearDown();
};
void RawDataParserTest::SetUpTestCase(void)
{
}
void RawDataParserTest::TearDownTestCase(void)
{
}
void RawDataParserTest::SetUp(void)
{
}
void RawDataParserTest::TearDown(void)
{
}
/**
* @tc.name: BigInt_Parser
* @tc.desc: test insert bigint to rdb store
* @tc.type: FUNC
*/
HWTEST_F(RawDataParserTest, BigInt_Parser, TestSize.Level1)
{
std::vector<uint64_t> u64Val(2 + rand() % 100, 0);
for (int i = 0; i < u64Val.size(); ++i) {
uint64_t high = uint64_t(rand());
uint64_t low = uint64_t(rand());
u64Val[i] = (high << 32) | low;
}
BigInteger value1 = BigInteger(0, std::vector<uint64_t>(u64Val));
auto rawData = RawDataParser::PackageRawData(value1);
for (size_t i = 0; i < sizeof(uintptr_t); ++i) {
std::vector<uint8_t> noAlign(rawData.size() + i, 0);
noAlign.insert(noAlign.begin() + i, rawData.begin(), rawData.end());
BigInteger parsedValue1;
RawDataParser::ParserRawData(noAlign.data() + i, noAlign.size() - i, parsedValue1);
ASSERT_TRUE(value1 == parsedValue1);
}
}
/**
* @tc.name: Float32_Parser
* @tc.desc: test insert bigint to rdb store
* @tc.type: FUNC
*/
HWTEST_F(RawDataParserTest, Float32_Parser, TestSize.Level1)
{
std::vector<float> floats(15, 9.65);
auto rawData = RawDataParser::PackageRawData(floats);
for (size_t i = 0; i < sizeof(uintptr_t); ++i) {
std::vector<uint8_t> noAlign(rawData.size() + i, 0);
noAlign.insert(noAlign.begin() + i, rawData.begin(), rawData.end());
std::vector<float> parsedFloats;
RawDataParser::ParserRawData(noAlign.data() + i, noAlign.size() - i, parsedFloats);
ASSERT_TRUE(floats.size() == parsedFloats.size());
}
}
/**
* @tc.name: Asset_Parser
* @tc.desc: test insert bigint to rdb store
* @tc.type: FUNC
*/
HWTEST_F(RawDataParserTest, Asset_Parser, TestSize.Level1)
{
ValueObject::Asset asset;
asset.id = "100";
asset.name = "IMG_1690.png";
asset.uri = "file://data/args/header/IMG_1690.png";
asset.createTime = "2024-07-05 20:37.982158265 +8:00";
asset.modifyTime = "2024-07-05 20:37.982158265 +8:00";
asset.size = "4194304";
asset.hash = "2024-07-05 20:37.982158265 +8:00_4194304";
asset.path = "photos/header/IMG_1690.png";
auto rawData = RawDataParser::PackageRawData(asset);
for (size_t i = 0; i < sizeof(uintptr_t); ++i) {
std::vector<uint8_t> noAlign(rawData.size() + i, 0);
noAlign.insert(noAlign.begin() + i, rawData.begin(), rawData.end());
ValueObject::Asset parsedAsset;
RawDataParser::ParserRawData(noAlign.data() + i, noAlign.size() - i, parsedAsset);
ASSERT_TRUE(parsedAsset.id == asset.id);
ASSERT_TRUE(parsedAsset.name == asset.name);
ASSERT_TRUE(parsedAsset.uri == asset.uri);
ASSERT_TRUE(parsedAsset.createTime == asset.createTime);
ASSERT_TRUE(parsedAsset.modifyTime == asset.modifyTime);
ASSERT_TRUE(parsedAsset.size == asset.size);
ASSERT_TRUE(parsedAsset.hash == asset.hash);
ASSERT_TRUE(parsedAsset.path == asset.path);
}
}
/**
* @tc.name: Assets_Parser
* @tc.desc: test insert bigint to rdb store
* @tc.type: FUNC
*/
HWTEST_F(RawDataParserTest, Assets_Parser, TestSize.Level1)
{
ValueObject::Assets assets(1);
assets[0].id = "100";
assets[0].name = "IMG_1690.png";
assets[0].uri = "file://data/args/header/IMG_1690.png";
assets[0].createTime = "2024-07-05 20:37.982158265 +8:00";
assets[0].modifyTime = "2024-07-05 20:37.982158265 +8:00";
assets[0].size = "4194304";
assets[0].hash = "2024-07-05 20:37.982158265 +8:00_4194304";
assets[0].path = "photos/header/IMG_1690.png";
auto rawData = RawDataParser::PackageRawData(assets);
for (size_t i = 0; i < sizeof(uintptr_t); ++i) {
std::vector<uint8_t> noAlign(rawData.size() + i, 0);
noAlign.insert(noAlign.begin() + i, rawData.begin(), rawData.end());
ValueObject::Assets parsedAssets;
RawDataParser::ParserRawData(noAlign.data() + i, noAlign.size() - i, parsedAssets);
ASSERT_TRUE(parsedAssets[0].id == assets[0].id);
ASSERT_TRUE(parsedAssets[0].name == assets[0].name);
ASSERT_TRUE(parsedAssets[0].uri == assets[0].uri);
ASSERT_TRUE(parsedAssets[0].createTime == assets[0].createTime);
ASSERT_TRUE(parsedAssets[0].modifyTime == assets[0].modifyTime);
ASSERT_TRUE(parsedAssets[0].size == assets[0].size);
ASSERT_TRUE(parsedAssets[0].hash == assets[0].hash);
ASSERT_TRUE(parsedAssets[0].path == assets[0].path);
}
}
} // namespace Test