mirror of
https://gitee.com/openharmony/distributeddatamgr_relational_store
synced 2025-02-17 00:39:02 +00:00
Add attach api
Signed-off-by: changjiaxing <changjiaxing2@huawei.com> Change-Id: Ica26d9c262082021e0478e31e108fc2c4a7217a0
This commit is contained in:
parent
001e090220
commit
0a7eeac889
@ -29,13 +29,13 @@ AlwaysBreakAfterReturnType: None
|
||||
|
||||
AlwaysBreakBeforeMultilineStrings: false
|
||||
|
||||
AlwaysBreakTemplateDeclarations: false
|
||||
AlwaysBreakTemplateDeclarations: true
|
||||
|
||||
BinPackArguments: true
|
||||
|
||||
BinPackParameters: true
|
||||
|
||||
BreakBeforeBinaryOperators: NonAssignment
|
||||
BreakBeforeBinaryOperators: false
|
||||
|
||||
BreakBeforeBraces: Custom
|
||||
|
||||
|
@ -41,11 +41,11 @@ int32_t Convert2Value(napi_env env, napi_value input, ExtraData &output)
|
||||
if (status != napi_ok || type != napi_object) {
|
||||
return napi_invalid_arg;
|
||||
}
|
||||
int32_t result = GET_PROPERTY(env, input, output, eventId);
|
||||
int32_t result = GetNamedProperty(env, input, "eventId", output.eventId);
|
||||
if (result != napi_ok) {
|
||||
return napi_invalid_arg;
|
||||
}
|
||||
return GET_PROPERTY(env, input, output, extraData);
|
||||
return GetNamedProperty(env, input, "extraData", output.extraData);
|
||||
}
|
||||
|
||||
template<>
|
||||
@ -57,18 +57,18 @@ int32_t Convert2Value(napi_env env, napi_value input, Participant &output)
|
||||
LOG_DEBUG("napi_typeof failed status = %{public}d type = %{public}d", status, type);
|
||||
return napi_invalid_arg;
|
||||
}
|
||||
NAPI_CALL_RETURN_ERR(GET_PROPERTY(env, input, output, identity), napi_invalid_arg);
|
||||
NAPI_CALL_RETURN_ERR(GetOptionalValue(env, input, "role", output.role), napi_invalid_arg);
|
||||
NAPI_CALL_RETURN_ERR(GetNamedProperty(env, input, "identity", output.identity), napi_invalid_arg);
|
||||
NAPI_CALL_RETURN_ERR(GetNamedProperty(env, input, "role", output.role, true), napi_invalid_arg);
|
||||
if (output.role < CloudData::Role::ROLE_NIL || output.role >= CloudData::Role::ROLE_BUTT) {
|
||||
return napi_invalid_arg;
|
||||
}
|
||||
NAPI_CALL_RETURN_ERR(GetOptionalValue(env, input, "state", output.state), napi_invalid_arg);
|
||||
NAPI_CALL_RETURN_ERR(GetNamedProperty(env, input, "state", output.state, true), napi_invalid_arg);
|
||||
if (output.state < CloudData::Confirmation::CFM_NIL ||
|
||||
output.state >= CloudData::Confirmation::CFM_BUTT) {
|
||||
return napi_invalid_arg;
|
||||
}
|
||||
NAPI_CALL_RETURN_ERR(GetOptionalValue(env, input, "privilege", output.privilege), napi_invalid_arg);
|
||||
NAPI_CALL_RETURN_ERR(GetOptionalValue(env, input, "attachInfo", output.attachInfo), napi_invalid_arg);
|
||||
NAPI_CALL_RETURN_ERR(GetNamedProperty(env, input, "privilege", output.privilege, true), napi_invalid_arg);
|
||||
NAPI_CALL_RETURN_ERR(GetNamedProperty(env, input, "attachInfo", output.attachInfo, true), napi_invalid_arg);
|
||||
return napi_ok;
|
||||
}
|
||||
|
||||
@ -81,11 +81,11 @@ int32_t Convert2Value(napi_env env, napi_value input, Privilege &output)
|
||||
LOG_DEBUG("napi_typeof failed status = %{public}d type = %{public}d", status, type);
|
||||
return napi_invalid_arg;
|
||||
}
|
||||
NAPI_CALL_RETURN_ERR(GetOptionalValue(env, input, "writable", output.writable), napi_invalid_arg);
|
||||
NAPI_CALL_RETURN_ERR(GetOptionalValue(env, input, "readable", output.readable), napi_invalid_arg);
|
||||
NAPI_CALL_RETURN_ERR(GetOptionalValue(env, input, "creatable", output.creatable), napi_invalid_arg);
|
||||
NAPI_CALL_RETURN_ERR(GetOptionalValue(env, input, "deletable", output.deletable), napi_invalid_arg);
|
||||
NAPI_CALL_RETURN_ERR(GetOptionalValue(env, input, "shareable", output.shareable), napi_invalid_arg);
|
||||
NAPI_CALL_RETURN_ERR(GetNamedProperty(env, input, "writable", output.writable, true), napi_invalid_arg);
|
||||
NAPI_CALL_RETURN_ERR(GetNamedProperty(env, input, "readable", output.readable, true), napi_invalid_arg);
|
||||
NAPI_CALL_RETURN_ERR(GetNamedProperty(env, input, "creatable", output.creatable, true), napi_invalid_arg);
|
||||
NAPI_CALL_RETURN_ERR(GetNamedProperty(env, input, "deletable", output.deletable, true), napi_invalid_arg);
|
||||
NAPI_CALL_RETURN_ERR(GetNamedProperty(env, input, "shareable", output.shareable, true), napi_invalid_arg);
|
||||
return napi_ok;
|
||||
}
|
||||
|
||||
@ -101,17 +101,14 @@ int32_t Convert2Value(napi_env env, napi_value jsValue, Asset &output)
|
||||
return napi_invalid_arg;
|
||||
}
|
||||
|
||||
NAPI_CALL_RETURN_ERR(GET_PROPERTY(env, jsValue, output, name), napi_invalid_arg);
|
||||
NAPI_CALL_RETURN_ERR(GET_PROPERTY(env, jsValue, output, uri), napi_invalid_arg);
|
||||
NAPI_CALL_RETURN_ERR(GET_PROPERTY(env, jsValue, output, createTime), napi_invalid_arg);
|
||||
NAPI_CALL_RETURN_ERR(GET_PROPERTY(env, jsValue, output, modifyTime), napi_invalid_arg);
|
||||
NAPI_CALL_RETURN_ERR(GET_PROPERTY(env, jsValue, output, size), napi_invalid_arg);
|
||||
NAPI_CALL_RETURN_ERR(GET_PROPERTY(env, jsValue, output, path), napi_invalid_arg);
|
||||
NAPI_CALL_RETURN_ERR(GetNamedProperty(env, jsValue, "name", output.name), napi_invalid_arg);
|
||||
NAPI_CALL_RETURN_ERR(GetNamedProperty(env, jsValue, "uri", output.uri), napi_invalid_arg);
|
||||
NAPI_CALL_RETURN_ERR(GetNamedProperty(env, jsValue, "createTime", output.createTime), napi_invalid_arg);
|
||||
NAPI_CALL_RETURN_ERR(GetNamedProperty(env, jsValue, "modifyTime", output.modifyTime), napi_invalid_arg);
|
||||
NAPI_CALL_RETURN_ERR(GetNamedProperty(env, jsValue, "modifyTime", output.size), napi_invalid_arg);
|
||||
NAPI_CALL_RETURN_ERR(GetNamedProperty(env, jsValue, "path", output.path), napi_invalid_arg);
|
||||
NAPI_CALL_RETURN_ERR(GetNamedProperty(env, jsValue, "status", output.status, true), napi_invalid_arg);
|
||||
output.hash = output.modifyTime + "_" + output.size;
|
||||
auto jsStatus = GetNamedProperty(env, jsValue, "status");
|
||||
if (jsStatus != nullptr) {
|
||||
Convert2ValueExt(env, jsStatus, output.status);
|
||||
}
|
||||
if (output.status != Asset::STATUS_DELETE) {
|
||||
output.status = Asset::STATUS_UNKNOWN;
|
||||
}
|
||||
|
@ -18,8 +18,8 @@
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
#include "ability.h"
|
||||
#include "napi/native_api.h"
|
||||
#include "ability.h"
|
||||
#include "napi/native_common.h"
|
||||
#include "napi/native_node_api.h"
|
||||
#include "napi_base_context.h"
|
||||
|
@ -16,14 +16,18 @@
|
||||
#ifndef DISTRIBUTEDDATAMGR_APPDATAMGR_JSUTILS_H
|
||||
#define DISTRIBUTEDDATAMGR_APPDATAMGR_JSUTILS_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <functional>
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <variant>
|
||||
#include <vector>
|
||||
#include <optional>
|
||||
|
||||
#include "napi/native_api.h"
|
||||
#include "napi/native_common.h"
|
||||
#include "napi/native_node_api.h"
|
||||
@ -31,35 +35,24 @@
|
||||
namespace OHOS {
|
||||
namespace AppDataMgrJsKit {
|
||||
namespace JSUtils {
|
||||
constexpr int OK = 0;
|
||||
constexpr int ERR = -1;
|
||||
constexpr uint32_t ASYNC_RST_SIZE = 2;
|
||||
constexpr uint32_t DEFAULT_VALUE_LENGTH = 1024;
|
||||
constexpr uint32_t MAX_VALUE_LENGTH = 1024 * 1024 * 8; // the max length of all kand of out string value
|
||||
constexpr uint32_t SYNC_RESULT_ELEMENT_NUM = 2;
|
||||
|
||||
static constexpr int OK = 0;
|
||||
static constexpr int ERR = -1;
|
||||
static constexpr uint32_t ASYNC_RST_SIZE = 2;
|
||||
static constexpr uint32_t DEFAULT_VALUE_LENGTH = 1024;
|
||||
static constexpr uint32_t MAX_VALUE_LENGTH = 1024 * 1024 * 8; // the max length of all kand of out string value
|
||||
static constexpr uint32_t SYNC_RESULT_ELEMENT_NUM = 2;
|
||||
struct JsFeatureSpace {
|
||||
const char* spaceName;
|
||||
const char* nameBase64;
|
||||
const char *spaceName;
|
||||
const char *nameBase64;
|
||||
bool isComponent;
|
||||
};
|
||||
|
||||
#ifndef ADD_JS_PROPERTY
|
||||
#define ADD_JS_PROPERTY(env, object, value, member) \
|
||||
napi_set_named_property((env), (object), #member, Convert2JSValue((env), (value).member))
|
||||
#endif
|
||||
|
||||
#ifndef GET_PROPERTY
|
||||
#define GET_PROPERTY(env, object, value, member) \
|
||||
Convert2Value((env), GetNamedProperty((env), (object), #member), (value).member)
|
||||
#endif
|
||||
|
||||
napi_value GetNamedProperty(napi_env env, napi_value object, const char *name);
|
||||
std::pair<int32_t, napi_value> GetOptionalNamedProperty(napi_env env, napi_value input, const char *name);
|
||||
|
||||
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);
|
||||
int32_t Convert2Value(napi_env env, napi_value jsValue, int64_t &output);
|
||||
@ -77,7 +70,7 @@ template<typename T>
|
||||
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, T &output);
|
||||
|
||||
template<typename T>
|
||||
int32_t Convert2Value(napi_env env, napi_value jsValue, std::vector<T> &value);
|
||||
@ -129,22 +122,6 @@ napi_value Convert2JSValue(napi_env env, const std::variant<Types...> &value);
|
||||
template<typename T>
|
||||
std::string ToString(const T &key);
|
||||
|
||||
template <typename T>
|
||||
int32_t GetOptionalValue(napi_env env, napi_value in, const char *name, T& out)
|
||||
{
|
||||
auto [status, value] = GetOptionalNamedProperty(env, in, name);
|
||||
if (status != napi_ok) {
|
||||
return status;
|
||||
}
|
||||
if (value == nullptr) {
|
||||
return napi_ok;
|
||||
}
|
||||
if (std::is_same_v<T, int32_t>) {
|
||||
return JSUtils::Convert2ValueExt(env, value, out);
|
||||
}
|
||||
return JSUtils::Convert2Value(env, value, out);
|
||||
}
|
||||
|
||||
template<typename K>
|
||||
std::enable_if_t<!std::is_same_v<K, std::string>, std::string> ConvertMapKey(const K &key)
|
||||
{
|
||||
@ -190,6 +167,36 @@ napi_value GetJSValue(napi_env env, const T &value)
|
||||
}
|
||||
return GetJSValue<T, Types...>(env, value);
|
||||
}
|
||||
|
||||
std::pair<napi_status, napi_value> GetInnerValue(napi_env env, napi_value in, const std::string &prop, bool optional);
|
||||
|
||||
template<typename T>
|
||||
inline std::enable_if_t<std::is_same_v<T, int32_t> || std::is_same_v<T, uint32_t>, int32_t> GetNamedProperty(
|
||||
napi_env env, napi_value in, const std::string &prop, T &value, bool optional = false)
|
||||
{
|
||||
auto [status, jsValue] = GetInnerValue(env, in, prop, optional);
|
||||
if (jsValue == nullptr) {
|
||||
return status;
|
||||
}
|
||||
return Convert2ValueExt(env, jsValue, value);
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
inline std::enable_if_t<!std::is_same_v<T, int32_t> && !std::is_same_v<T, uint32_t>, int32_t> GetNamedProperty(
|
||||
napi_env env, napi_value in, const std::string &prop, T &value, bool optional = false)
|
||||
{
|
||||
auto [status, jsValue] = GetInnerValue(env, in, prop, optional);
|
||||
if (jsValue == nullptr) {
|
||||
return status;
|
||||
}
|
||||
return Convert2Value(env, jsValue, value);
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
inline int32_t SetNamedProperty(napi_env env, napi_value in, const std::string &prop, T value)
|
||||
{
|
||||
return napi_set_named_property(env, in, prop.c_str(), Convert2JSValue(env, value));
|
||||
};
|
||||
} // namespace JSUtils
|
||||
|
||||
template<typename T>
|
||||
|
@ -14,6 +14,7 @@
|
||||
*/
|
||||
|
||||
#include "js_utils.h"
|
||||
#include "js_native_api_types.h"
|
||||
#include "logger.h"
|
||||
#include <cstring>
|
||||
using namespace OHOS::Rdb;
|
||||
@ -53,29 +54,24 @@ const std::optional<JSUtils::JsFeatureSpace> JSUtils::GetJsFeatureSpace(const st
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
napi_value JSUtils::GetNamedProperty(napi_env env, napi_value object, const char *name)
|
||||
{
|
||||
napi_value jsItem = nullptr;
|
||||
napi_get_named_property(env, object, name, &jsItem);
|
||||
return jsItem;
|
||||
}
|
||||
|
||||
std::pair<int32_t, napi_value> JSUtils::GetOptionalNamedProperty(napi_env env, napi_value input, const char *name)
|
||||
std::pair<napi_status, napi_value> JSUtils::GetInnerValue(
|
||||
napi_env env, napi_value in, const std::string& prop, bool optional)
|
||||
{
|
||||
bool hasProp = false;
|
||||
napi_status status = napi_has_named_property(env, input, name, &hasProp);
|
||||
napi_status status = napi_has_named_property(env, in, prop.c_str(), &hasProp);
|
||||
if (status != napi_ok) {
|
||||
return std::make_pair(napi_generic_failure, nullptr);
|
||||
}
|
||||
if (!hasProp) {
|
||||
return std::make_pair(napi_ok, nullptr);
|
||||
status = optional ? napi_ok : napi_generic_failure;
|
||||
return std::make_pair(status, nullptr);
|
||||
}
|
||||
napi_value inner = nullptr;
|
||||
status = napi_get_named_property(env, input, name, &inner);
|
||||
status = napi_get_named_property(env, in, prop.c_str(), &inner);
|
||||
if (status != napi_ok || inner == nullptr) {
|
||||
return std::make_pair(napi_generic_failure, nullptr);
|
||||
}
|
||||
if (JSUtils::IsNull(env, inner)) {
|
||||
if (optional && JSUtils::IsNull(env, inner)) {
|
||||
return std::make_pair(napi_ok, nullptr);
|
||||
}
|
||||
return std::make_pair(napi_ok, inner);
|
||||
@ -122,6 +118,12 @@ int32_t JSUtils::Convert2ValueExt(napi_env env, napi_value jsValue, int32_t &out
|
||||
return status;
|
||||
}
|
||||
|
||||
int32_t JSUtils::Convert2Value(napi_env env, napi_value jsValue, napi_value &output)
|
||||
{
|
||||
output = jsValue;
|
||||
return napi_ok;
|
||||
}
|
||||
|
||||
int32_t JSUtils::Convert2Value(napi_env env, napi_value jsValue, bool &output)
|
||||
{
|
||||
napi_valuetype type = napi_undefined;
|
||||
@ -152,7 +154,7 @@ int32_t JSUtils::Convert2ValueExt(napi_env env, napi_value jsValue, int64_t &out
|
||||
|
||||
status = napi_get_value_int64(env, jsValue, &output);
|
||||
if (status != napi_ok) {
|
||||
LOG_DEBUG("napi_get_value_int32 failed, status = %{public}d", status);
|
||||
LOG_DEBUG("napi_get_value_int64 failed, status = %{public}d", status);
|
||||
return status;
|
||||
}
|
||||
return status;
|
||||
|
@ -33,14 +33,13 @@ int32_t Convert2Value(napi_env env, napi_value jsValue, Asset &output)
|
||||
return napi_invalid_arg;
|
||||
}
|
||||
|
||||
NAPI_CALL_BASE(env, Convert2ValueExt(env, GetNamedProperty(env, jsValue, "version"), output.version),
|
||||
napi_invalid_arg);
|
||||
NAPI_CALL_BASE(env, GET_PROPERTY(env, jsValue, output, name), napi_invalid_arg);
|
||||
NAPI_CALL_BASE(env, GET_PROPERTY(env, jsValue, output, uri), napi_invalid_arg);
|
||||
NAPI_CALL_BASE(env, GET_PROPERTY(env, jsValue, output, createTime), napi_invalid_arg);
|
||||
NAPI_CALL_BASE(env, GET_PROPERTY(env, jsValue, output, modifyTime), napi_invalid_arg);
|
||||
NAPI_CALL_BASE(env, GET_PROPERTY(env, jsValue, output, size), napi_invalid_arg);
|
||||
NAPI_CALL_BASE(env, GET_PROPERTY(env, jsValue, output, hash), napi_invalid_arg);
|
||||
NAPI_CALL_BASE(env, GetNamedProperty(env, jsValue, "version", output.version), napi_invalid_arg);
|
||||
NAPI_CALL_BASE(env, GetNamedProperty(env, jsValue, "name", output.name), napi_invalid_arg);
|
||||
NAPI_CALL_BASE(env, GetNamedProperty(env, jsValue, "uri", output.uri), napi_invalid_arg);
|
||||
NAPI_CALL_BASE(env, GetNamedProperty(env, jsValue, "createTime", output.createTime), napi_invalid_arg);
|
||||
NAPI_CALL_BASE(env, GetNamedProperty(env, jsValue, "modifyTime", output.modifyTime), napi_invalid_arg);
|
||||
NAPI_CALL_BASE(env, GetNamedProperty(env, jsValue, "size", output.size), napi_invalid_arg);
|
||||
NAPI_CALL_BASE(env, GetNamedProperty(env, jsValue, "hash", output.hash), napi_invalid_arg);
|
||||
return napi_ok;
|
||||
}
|
||||
|
||||
@ -49,13 +48,13 @@ napi_value Convert2JSValue(napi_env env, const Asset &value)
|
||||
{
|
||||
napi_value object = nullptr;
|
||||
NAPI_CALL_BASE(env, napi_create_object(env, &object), object);
|
||||
NAPI_CALL_BASE(env, ADD_JS_PROPERTY(env, object, value, version), object);
|
||||
NAPI_CALL_BASE(env, ADD_JS_PROPERTY(env, object, value, name), object);
|
||||
NAPI_CALL_BASE(env, ADD_JS_PROPERTY(env, object, value, uri), object);
|
||||
NAPI_CALL_BASE(env, ADD_JS_PROPERTY(env, object, value, createTime), object);
|
||||
NAPI_CALL_BASE(env, ADD_JS_PROPERTY(env, object, value, modifyTime), object);
|
||||
NAPI_CALL_BASE(env, ADD_JS_PROPERTY(env, object, value, size), object);
|
||||
NAPI_CALL_BASE(env, ADD_JS_PROPERTY(env, object, value, hash), object);
|
||||
NAPI_CALL_BASE(env, SetNamedProperty(env, object, "version", value.version), object);
|
||||
NAPI_CALL_BASE(env, SetNamedProperty(env, object, "name", value.name), object);
|
||||
NAPI_CALL_BASE(env, SetNamedProperty(env, object, "uri", value.uri), object);
|
||||
NAPI_CALL_BASE(env, SetNamedProperty(env, object, "createTime", value.createTime), object);
|
||||
NAPI_CALL_BASE(env, SetNamedProperty(env, object, "modifyTime", value.modifyTime), object);
|
||||
NAPI_CALL_BASE(env, SetNamedProperty(env, object, "size", value.size), object);
|
||||
NAPI_CALL_BASE(env, SetNamedProperty(env, object, "hash", value.hash), object);
|
||||
return object;
|
||||
}
|
||||
|
||||
|
@ -515,7 +515,7 @@ napi_value InnerDeleteRdbStore(napi_env env, napi_callback_info info, std::share
|
||||
int errCode = RdbHelper::DeleteRdbStore(context->config.GetPath());
|
||||
LOG_DEBUG("RdbJsKit::DeleteRdbStore failed %{public}d", errCode);
|
||||
std::shared_ptr<Error> dbInvalidError = std::make_shared<DbInvalidError>();
|
||||
RDB_CHECK_RETURN_CALL_RESULT(errCode != E_EMPTY_FILE_NAME, context->SetError(dbInvalidError));
|
||||
RDB_CHECK_RETURN_CALL_RESULT(errCode != E_INVALID_FILE_PATH, context->SetError(dbInvalidError));
|
||||
return (errCode == E_OK) ? OK : ERR;
|
||||
};
|
||||
auto output = [context](napi_env env, napi_value &result) -> int {
|
||||
|
@ -28,6 +28,7 @@ sources = [
|
||||
"src/entry_point.cpp",
|
||||
"src/napi_async_call.cpp",
|
||||
"src/napi_rdb_const_properties.cpp",
|
||||
"src/napi_rdb_error.cpp",
|
||||
"src/napi_rdb_js_utils.cpp",
|
||||
"src/napi_rdb_predicates.cpp",
|
||||
"src/napi_rdb_store.cpp",
|
||||
|
@ -35,12 +35,12 @@ extern bool g_sync;
|
||||
#define ASYNC &g_async
|
||||
#define SYNC &g_sync
|
||||
|
||||
class Context {
|
||||
class ContextBase {
|
||||
public:
|
||||
void SetAction(napi_env env, napi_callback_info info, InputAction input, ExecuteAction exec, OutputAction output);
|
||||
void SetAll(napi_env env, napi_callback_info info, InputAction input, ExecuteAction exec, OutputAction output);
|
||||
void SetError(std::shared_ptr<Error> error);
|
||||
virtual ~Context();
|
||||
virtual ~ContextBase();
|
||||
|
||||
napi_env env_ = nullptr;
|
||||
bool isAsync_ = true;
|
||||
@ -56,12 +56,12 @@ public:
|
||||
OutputAction output_ = nullptr;
|
||||
ExecuteAction exec_ = nullptr;
|
||||
napi_value result_ = nullptr;
|
||||
std::shared_ptr<Context> keep_;
|
||||
std::shared_ptr<ContextBase> keep_;
|
||||
};
|
||||
|
||||
class AsyncCall final {
|
||||
public:
|
||||
static napi_value Call(napi_env env, std::shared_ptr<Context> context);
|
||||
static napi_value Call(napi_env env, std::shared_ptr<ContextBase> context);
|
||||
|
||||
private:
|
||||
enum { ARG_ERROR, ARG_DATA, ARG_BUTT };
|
||||
@ -70,8 +70,8 @@ private:
|
||||
static void OnReturn(napi_env env, napi_status status, void *data);
|
||||
static void OnComplete(napi_env env, napi_status status, void *data);
|
||||
static void SetBusinessError(napi_env env, std::shared_ptr<Error> error, napi_value *businessError);
|
||||
static napi_value Async(napi_env env, std::shared_ptr<Context> context);
|
||||
static napi_value Sync(napi_env env, std::shared_ptr<Context> context);
|
||||
static napi_value Async(napi_env env, std::shared_ptr<ContextBase> context);
|
||||
static napi_value Sync(napi_env env, std::shared_ptr<ContextBase> context);
|
||||
};
|
||||
} // namespace RelationalStoreJsKit
|
||||
} // namespace OHOS
|
||||
|
@ -26,28 +26,31 @@ constexpr int MAX_INPUT_COUNT = 10;
|
||||
constexpr int OK = 0;
|
||||
constexpr int ERR = -1;
|
||||
|
||||
constexpr int E_PARAM_ERROR = 401;
|
||||
constexpr int E_NON_SYSTEM_APP_ERROR = 202;
|
||||
constexpr int E_PARAM_ERROR = 401;
|
||||
constexpr int E_NOT_SUPPORTED = 801;
|
||||
constexpr int E_INNER_ERROR = 14800000;
|
||||
constexpr int E_RESULT_GOTO_ERROR = 14800012;
|
||||
constexpr int E_NOT_STAGE_MODE = 14801001;
|
||||
constexpr int E_DATA_GROUP_ID_INVALID = 14801002;
|
||||
|
||||
const static std::map<int, std::string> ERROR_MAPS = {
|
||||
{ NativeRdb::E_WAL_SIZE_OVER_LIMIT, "The WAL file size over default limit." },
|
||||
{ NativeRdb::E_EMPTY_FILE_NAME, "Failed to open or delete database by invalid database path." },
|
||||
{ NativeRdb::E_INVALID_FILE_PATH, "Failed to open database by database corrupted" },
|
||||
{ NativeRdb::E_NOT_SUPPORTED, "Capability not supported" },
|
||||
{ E_RESULT_GOTO_ERROR, "The result set is empty or the specified location is invalid." },
|
||||
{ NativeRdb::E_INVALID_STATEMENT, "The column value is null or the column type is incompatible." },
|
||||
{ E_NOT_STAGE_MODE, "Only supported in stage mode." },
|
||||
{ E_DATA_GROUP_ID_INVALID, "The data group id is invalid." },
|
||||
{ NativeRdb::E_GET_DATAOBSMGRCLIENT_FAIL, "Failed to get DataObsMgrClient." },
|
||||
{ NativeRdb::E_TYPE_MISMATCH, "The type of the distributed table does not match" },
|
||||
{ NativeRdb::E_DATABASE_FULL, "database or disk is full." }
|
||||
struct JsErrorCode {
|
||||
int32_t status;
|
||||
int32_t jsCode;
|
||||
const char *message;
|
||||
};
|
||||
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
|
||||
|
||||
#define RDB_NAPI_ASSERT_BASE(env, assertion, error, retVal) \
|
||||
do { \
|
||||
@ -101,10 +104,11 @@ class InnerError : public Error {
|
||||
public:
|
||||
InnerError(int code)
|
||||
{
|
||||
auto iter = ERROR_MAPS.find(code);
|
||||
if (iter != ERROR_MAPS.end()) {
|
||||
code_ = code;
|
||||
msg_ = iter->second;
|
||||
auto errorMsg = GetJsErrorCode(code);
|
||||
if (errorMsg.has_value()) {
|
||||
auto napiError = errorMsg.value();
|
||||
code_ = napiError.jsCode;
|
||||
msg_ = napiError.message;
|
||||
} else {
|
||||
code_ = E_INNER_ERROR;
|
||||
msg_ = "Inner error. Inner code is " + std::to_string(code % E_INNER_ERROR);
|
||||
@ -133,19 +137,28 @@ private:
|
||||
|
||||
class ParamError : public Error {
|
||||
public:
|
||||
ParamError(const std::string &needed, const std::string &mustbe) : needed_(needed), mustbe_(mustbe){};
|
||||
ParamError(const std::string &needed, const std::string &mustbe)
|
||||
{
|
||||
msg_ = "Parameter error. The " + needed + " must be " + mustbe;
|
||||
};
|
||||
|
||||
ParamError(const std::string &errMsg)
|
||||
{
|
||||
msg_ = "Parameter error." + errMsg;
|
||||
}
|
||||
|
||||
std::string GetMessage() override
|
||||
{
|
||||
return "Parameter error. The " + needed_ + " must be " + mustbe_;
|
||||
return msg_;
|
||||
};
|
||||
|
||||
int GetCode() override
|
||||
{
|
||||
return E_PARAM_ERROR;
|
||||
};
|
||||
|
||||
private:
|
||||
std::string needed_;
|
||||
std::string mustbe_;
|
||||
std::string msg_;
|
||||
};
|
||||
|
||||
class NonSystemError : public Error {
|
||||
|
@ -16,13 +16,14 @@
|
||||
#ifndef RDB_JSKIT_NAPI_RDB_JS_UTILS_H
|
||||
#define RDB_JSKIT_NAPI_RDB_JS_UTILS_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include "asset_value.h"
|
||||
#include "js_utils.h"
|
||||
#include "napi_rdb_error.h"
|
||||
#include "napi_rdb_store_observer.h"
|
||||
#include "rdb_store_config.h"
|
||||
#include "result_set.h"
|
||||
#include "value_object.h"
|
||||
#include "rdb_types.h"
|
||||
|
||||
namespace OHOS::AppDataMgrJsKit {
|
||||
namespace JSUtils {
|
||||
using Asset = OHOS::NativeRdb::AssetValue;
|
||||
@ -31,6 +32,29 @@ using ValueObject = OHOS::NativeRdb::ValueObject;
|
||||
using Date = OHOS::DistributedRdb::Date;
|
||||
using JSChangeInfo = OHOS::RelationalStoreJsKit::NapiRdbStoreObserver::JSChangeInfo;
|
||||
using PRIKey = OHOS::DistributedRdb::RdbStoreObserver::PrimaryKey;
|
||||
using Error = RelationalStoreJsKit::Error;
|
||||
using SecurityLevel = NativeRdb::SecurityLevel;
|
||||
using RdbStoreConfig = NativeRdb::RdbStoreConfig;
|
||||
|
||||
struct RdbConfig {
|
||||
bool isEncrypt = false;
|
||||
bool isSearchable = false;
|
||||
bool isAutoClean = false;
|
||||
SecurityLevel securityLevel = SecurityLevel::LAST;
|
||||
std::string dataGroupId;
|
||||
std::string name;
|
||||
std::string customDir;
|
||||
std::string path;
|
||||
};
|
||||
|
||||
struct ContextParam {
|
||||
std::string bundleName;
|
||||
std::string moduleName;
|
||||
std::string baseDir;
|
||||
int32_t area;
|
||||
bool isSystemApp = false;
|
||||
bool isStageMode = true;
|
||||
};
|
||||
|
||||
template<>
|
||||
int32_t Convert2Value(napi_env env, napi_value input, Asset &output);
|
||||
@ -44,6 +68,12 @@ int32_t Convert2Value(napi_env env, napi_value jsValue, DistributedRdb::Distribu
|
||||
template<>
|
||||
int32_t Convert2Value(napi_env env, napi_value jsValue, ValueObject &valueObject);
|
||||
|
||||
template<>
|
||||
int32_t Convert2Value(napi_env env, napi_value jsValue, RdbConfig &rdbConfig);
|
||||
|
||||
template<>
|
||||
int32_t Convert2Value(napi_env env, napi_value jsValue, ContextParam &context);
|
||||
|
||||
template<>
|
||||
napi_value Convert2JSValue(napi_env env, const Asset &value);
|
||||
|
||||
@ -69,6 +99,13 @@ template<>
|
||||
napi_value Convert2JSValue(napi_env env, const Date &date);
|
||||
template<>
|
||||
std::string ToString(const PRIKey &key);
|
||||
|
||||
bool IsNapiString(napi_env env, napi_value value);
|
||||
|
||||
std::tuple<int32_t, std::shared_ptr<Error>> GetRealPath(
|
||||
napi_env env, napi_value jsValue, RdbConfig &rdbConfig, ContextParam ¶m);
|
||||
RdbStoreConfig GetRdbStoreConfig(const RdbConfig &rdbConfig, const ContextParam ¶m);
|
||||
|
||||
}; // namespace JSUtils
|
||||
} // namespace OHOS::AppDataMgrJsKit
|
||||
#endif // RDB_JSKIT_NAPI_RDB_JS_UTILS_H
|
@ -55,6 +55,7 @@ private:
|
||||
static napi_value Count(napi_env env, napi_callback_info info);
|
||||
static napi_value Replace(napi_env env, napi_callback_info info);
|
||||
static napi_value Attach(napi_env env, napi_callback_info info);
|
||||
static napi_value Detach(napi_env env, napi_callback_info info);
|
||||
static napi_value GetPath(napi_env env, napi_callback_info info);
|
||||
static napi_value IsMemoryRdb(napi_env env, napi_callback_info info);
|
||||
static napi_value IsHoldingConnection(napi_env env, napi_callback_info info);
|
||||
@ -80,6 +81,8 @@ private:
|
||||
static napi_value QuerySharingResource(napi_env env, napi_callback_info info);
|
||||
|
||||
static constexpr int EVENT_HANDLE_NUM = 2;
|
||||
static constexpr int WAIT_TIME_DEFAULT = 2;
|
||||
static constexpr int WAIT_TIME_LIMIT = 300;
|
||||
|
||||
napi_value OnRemote(napi_env env, size_t argc, napi_value *argv);
|
||||
napi_value OnLocal(napi_env env, const DistributedRdb::SubscribeOption &option, napi_value callback);
|
||||
|
@ -52,6 +52,7 @@ private:
|
||||
static napi_value Count(napi_env env, napi_callback_info info);
|
||||
static napi_value Replace(napi_env env, napi_callback_info info);
|
||||
static napi_value Attach(napi_env env, napi_callback_info info);
|
||||
static napi_value Detach(napi_env env, napi_callback_info info);
|
||||
static napi_value GetPath(napi_env env, napi_callback_info info);
|
||||
static napi_value IsMemoryRdb(napi_env env, napi_callback_info info);
|
||||
static napi_value IsHoldingConnection(napi_env env, napi_callback_info info);
|
||||
|
@ -26,7 +26,7 @@ namespace OHOS {
|
||||
namespace RelationalStoreJsKit {
|
||||
bool g_async = true; // do not reset the value, used in DECLARE_NAPI_FUNCTION_WITH_DATA only
|
||||
bool g_sync = false; // do not reset the value, used in DECLARE_NAPI_FUNCTION_WITH_DATA only
|
||||
void Context::SetAction(
|
||||
void ContextBase::SetAction(
|
||||
napi_env env, napi_callback_info info, InputAction input, ExecuteAction exec, OutputAction output)
|
||||
{
|
||||
env_ = env;
|
||||
@ -59,7 +59,7 @@ void Context::SetAction(
|
||||
napi_create_reference(env, self, 1, &self_);
|
||||
}
|
||||
|
||||
void Context::SetAll(
|
||||
void ContextBase::SetAll(
|
||||
napi_env env, napi_callback_info info, InputAction input, ExecuteAction exec, OutputAction output)
|
||||
{
|
||||
env_ = env;
|
||||
@ -78,12 +78,12 @@ void Context::SetAll(
|
||||
napi_create_reference(env, self, 1, &self_);
|
||||
}
|
||||
|
||||
void Context::SetError(std::shared_ptr<Error> err)
|
||||
void ContextBase::SetError(std::shared_ptr<Error> err)
|
||||
{
|
||||
error = err;
|
||||
}
|
||||
|
||||
Context::~Context()
|
||||
ContextBase::~ContextBase()
|
||||
{
|
||||
if (env_ == nullptr) {
|
||||
return;
|
||||
@ -113,12 +113,12 @@ void AsyncCall::SetBusinessError(napi_env env, std::shared_ptr<Error> error, nap
|
||||
}
|
||||
}
|
||||
|
||||
napi_value AsyncCall::Call(napi_env env, std::shared_ptr<Context> context)
|
||||
napi_value AsyncCall::Call(napi_env env, std::shared_ptr<ContextBase> context)
|
||||
{
|
||||
return context->isAsync_ ? Async(env, context) : Sync(env, context);
|
||||
}
|
||||
|
||||
napi_value AsyncCall::Async(napi_env env, std::shared_ptr<Context> context)
|
||||
napi_value AsyncCall::Async(napi_env env, std::shared_ptr<ContextBase> context)
|
||||
{
|
||||
napi_value promise = nullptr;
|
||||
if (context->callback_ == nullptr) {
|
||||
@ -142,7 +142,7 @@ napi_value AsyncCall::Async(napi_env env, std::shared_ptr<Context> context)
|
||||
return promise;
|
||||
}
|
||||
|
||||
napi_value AsyncCall::Sync(napi_env env, std::shared_ptr<Context> context)
|
||||
napi_value AsyncCall::Sync(napi_env env, std::shared_ptr<ContextBase> context)
|
||||
{
|
||||
OnExecute(env, reinterpret_cast<void *>(context.get()));
|
||||
OnComplete(env, reinterpret_cast<void *>(context.get()));
|
||||
@ -152,7 +152,7 @@ napi_value AsyncCall::Sync(napi_env env, std::shared_ptr<Context> context)
|
||||
void AsyncCall::OnExecute(napi_env env, void *data)
|
||||
{
|
||||
DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__));
|
||||
Context *context = reinterpret_cast<Context *>(data);
|
||||
ContextBase *context = reinterpret_cast<ContextBase *>(data);
|
||||
if (context->error == nullptr && context->exec_) {
|
||||
context->execCode_ = context->exec_();
|
||||
}
|
||||
@ -161,7 +161,7 @@ void AsyncCall::OnExecute(napi_env env, void *data)
|
||||
|
||||
void AsyncCall::OnComplete(napi_env env, void *data)
|
||||
{
|
||||
Context *context = reinterpret_cast<Context *>(data);
|
||||
ContextBase *context = reinterpret_cast<ContextBase *>(data);
|
||||
if (context->execCode_ != NativeRdb::E_OK) {
|
||||
context->SetError(std::make_shared<InnerError>(context->execCode_));
|
||||
}
|
||||
@ -181,7 +181,7 @@ void AsyncCall::OnComplete(napi_env env, napi_status status, void *data)
|
||||
|
||||
void AsyncCall::OnReturn(napi_env env, napi_status status, void *data)
|
||||
{
|
||||
Context *context = reinterpret_cast<Context *>(data);
|
||||
ContextBase *context = reinterpret_cast<ContextBase *>(data);
|
||||
napi_value result[ARG_BUTT] = { 0 };
|
||||
// if out function status is ok then async renturn output data, else return error.
|
||||
if (context->error == nullptr) {
|
||||
|
53
frameworks/js/napi/relationalstore/src/napi_rdb_error.cpp
Normal file
53
frameworks/js/napi/relationalstore/src/napi_rdb_error.cpp
Normal file
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "napi_rdb_error.h"
|
||||
|
||||
namespace OHOS {
|
||||
namespace RelationalStoreJsKit {
|
||||
using JsErrorCode = OHOS::RelationalStoreJsKit::JsErrorCode;
|
||||
static constexpr JsErrorCode JS_ERROR_CODE_MSGS[] = {
|
||||
{ NativeRdb::E_NOT_SUPPORTED, 801, "Capability not supported." },
|
||||
{ NativeRdb::E_DATA_BASE_CORRUPTED, 14800011, "Database corrupted." },
|
||||
{ NativeRdb::E_INVALID_FILE_PATH, 14800010, "Invalid database path." },
|
||||
{ E_RESULT_GOTO_ERROR, 14800012, "The result set is empty or the specified location is invalid." },
|
||||
{ NativeRdb::E_INVALID_STATEMENT, 14800013, "The column value is null or the column type is incompatible." },
|
||||
{ NativeRdb::E_DATABASE_BUSY, 14800015, "The database does not respond." },
|
||||
{ NativeRdb::E_WAL_SIZE_OVER_LIMIT, 14800047, "The WAL file size over default limit." },
|
||||
{ NativeRdb::E_GET_DATAOBSMGRCLIENT_FAIL, 14801050, "Failed to get DataObsMgrClient." },
|
||||
{ NativeRdb::E_TYPE_MISMATCH, 14800051, "The type of the distributed table does not match." },
|
||||
{ NativeRdb::E_DATABASE_FULL, 14800052, "database or disk is full."},
|
||||
{ NativeRdb::E_ATTACHED_DATABASE_EXIST, 14800016, "The database is already attached."},
|
||||
{ E_NOT_STAGE_MODE, 14801001, "Only supported in stage mode." },
|
||||
{ E_DATA_GROUP_ID_INVALID, 14801002, "The data group id is invalid." }
|
||||
};
|
||||
|
||||
const std::optional<JsErrorCode> GetJsErrorCode(int32_t errorCode)
|
||||
{
|
||||
auto jsErrorCode = JsErrorCode{ errorCode, -1, "" };
|
||||
auto iter = std::lower_bound(JS_ERROR_CODE_MSGS,
|
||||
JS_ERROR_CODE_MSGS + sizeof(JS_ERROR_CODE_MSGS) / sizeof(JS_ERROR_CODE_MSGS[0]), jsErrorCode,
|
||||
[](const JsErrorCode &jsErrorCode1, const JsErrorCode &jsErrorCode2) {
|
||||
return jsErrorCode1.status < jsErrorCode2.status;
|
||||
});
|
||||
if (iter < JS_ERROR_CODE_MSGS + sizeof(JS_ERROR_CODE_MSGS) / sizeof(JS_ERROR_CODE_MSGS[0]) &&
|
||||
iter->status == errorCode) {
|
||||
return *iter;
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
} // namespace RelationalStoreJsKit
|
||||
} // namespace OHOS
|
@ -15,21 +15,32 @@
|
||||
|
||||
#include "napi_rdb_js_utils.h"
|
||||
|
||||
#include <memory>
|
||||
#include <tuple>
|
||||
|
||||
#include "js_ability.h"
|
||||
#include "js_native_api_types.h"
|
||||
#include "logger.h"
|
||||
#include "rdb_errno.h"
|
||||
#include "rdb_sql_utils.h"
|
||||
#include "result_set.h"
|
||||
|
||||
#define NAPI_CALL_RETURN_ERR(theCall, retVal) \
|
||||
do { \
|
||||
if ((theCall) != napi_ok) { \
|
||||
return retVal; \
|
||||
} \
|
||||
do { \
|
||||
if ((theCall) != napi_ok) { \
|
||||
return retVal; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#ifndef PATH_SPLIT
|
||||
#define PATH_SPLIT '/'
|
||||
#endif
|
||||
namespace OHOS::AppDataMgrJsKit {
|
||||
namespace JSUtils {
|
||||
using namespace OHOS::Rdb;
|
||||
using namespace NativeRdb;
|
||||
|
||||
using RelationalStoreJsKit::ParamError;
|
||||
using namespace RelationalStoreJsKit;
|
||||
template<>
|
||||
int32_t Convert2Value(napi_env env, napi_value jsValue, Asset &output)
|
||||
{
|
||||
@ -42,20 +53,17 @@ int32_t Convert2Value(napi_env env, napi_value jsValue, Asset &output)
|
||||
return napi_invalid_arg;
|
||||
}
|
||||
|
||||
NAPI_CALL_RETURN_ERR(GET_PROPERTY(env, jsValue, output, name), napi_invalid_arg);
|
||||
NAPI_CALL_RETURN_ERR(GET_PROPERTY(env, jsValue, output, uri), napi_invalid_arg);
|
||||
NAPI_CALL_RETURN_ERR(GET_PROPERTY(env, jsValue, output, createTime), napi_invalid_arg);
|
||||
NAPI_CALL_RETURN_ERR(GET_PROPERTY(env, jsValue, output, modifyTime), napi_invalid_arg);
|
||||
NAPI_CALL_RETURN_ERR(GET_PROPERTY(env, jsValue, output, size), napi_invalid_arg);
|
||||
NAPI_CALL_RETURN_ERR(GET_PROPERTY(env, jsValue, output, path), napi_invalid_arg);
|
||||
output.hash = output.modifyTime + "_" + output.size;
|
||||
auto jsStatus = GetNamedProperty(env, jsValue, "status");
|
||||
if (jsStatus != nullptr) {
|
||||
Convert2ValueExt(env, jsStatus, output.status);
|
||||
}
|
||||
NAPI_CALL_RETURN_ERR(GetNamedProperty(env, jsValue, "name", output.name), napi_invalid_arg);
|
||||
NAPI_CALL_RETURN_ERR(GetNamedProperty(env, jsValue, "uri", output.uri), napi_invalid_arg);
|
||||
NAPI_CALL_RETURN_ERR(GetNamedProperty(env, jsValue, "createTime", output.createTime), napi_invalid_arg);
|
||||
NAPI_CALL_RETURN_ERR(GetNamedProperty(env, jsValue, "modifyTime", output.modifyTime), napi_invalid_arg);
|
||||
NAPI_CALL_RETURN_ERR(GetNamedProperty(env, jsValue, "size", output.size), napi_invalid_arg);
|
||||
NAPI_CALL_RETURN_ERR(GetNamedProperty(env, jsValue, "path", output.path), napi_invalid_arg);
|
||||
NAPI_CALL_RETURN_ERR(GetNamedProperty(env, jsValue, "status", output.status, true), napi_invalid_arg);
|
||||
if (output.status != AssetValue::STATUS_DELETE) {
|
||||
output.status = AssetValue::STATUS_UNKNOWN;
|
||||
}
|
||||
output.hash = output.modifyTime + "_" + output.size;
|
||||
return napi_ok;
|
||||
}
|
||||
|
||||
@ -69,9 +77,9 @@ int32_t Convert2Value(napi_env env, napi_value input, DistributedRdb::Reference
|
||||
return napi_invalid_arg;
|
||||
}
|
||||
|
||||
NAPI_CALL_RETURN_ERR(GET_PROPERTY(env, input, output, sourceTable), napi_invalid_arg);
|
||||
NAPI_CALL_RETURN_ERR(GET_PROPERTY(env, input, output, targetTable), napi_invalid_arg);
|
||||
NAPI_CALL_RETURN_ERR(GET_PROPERTY(env, input, output, refFields), napi_invalid_arg);
|
||||
NAPI_CALL_RETURN_ERR(GetNamedProperty(env, input, "sourceTable", output.sourceTable), napi_invalid_arg);
|
||||
NAPI_CALL_RETURN_ERR(GetNamedProperty(env, input, "targetTable", output.targetTable), napi_invalid_arg);
|
||||
NAPI_CALL_RETURN_ERR(GetNamedProperty(env, input, "refFields", output.refFields), napi_invalid_arg);
|
||||
return napi_ok;
|
||||
}
|
||||
|
||||
@ -85,12 +93,8 @@ int32_t Convert2Value(napi_env env, napi_value input, DistributedRdb::Distribute
|
||||
return napi_invalid_arg;
|
||||
}
|
||||
|
||||
NAPI_CALL_RETURN_ERR(GET_PROPERTY(env, input, output, autoSync), napi_invalid_arg);
|
||||
bool exist = false;
|
||||
status = napi_has_named_property(env, input, "references", &exist);
|
||||
if (status == napi_ok && exist) {
|
||||
NAPI_CALL_RETURN_ERR(GET_PROPERTY(env, input, output, references), napi_invalid_arg);
|
||||
}
|
||||
NAPI_CALL_RETURN_ERR(GetNamedProperty(env, input, "autoSync", output.autoSync), napi_invalid_arg);
|
||||
NAPI_CALL_RETURN_ERR(GetNamedProperty(env, input, "references", output.references, true), napi_invalid_arg);
|
||||
return napi_ok;
|
||||
}
|
||||
|
||||
@ -109,28 +113,27 @@ 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(ADD_JS_PROPERTY(env, object, value, name), object);
|
||||
NAPI_CALL_RETURN_ERR(ADD_JS_PROPERTY(env, object, value, uri), object);
|
||||
NAPI_CALL_RETURN_ERR(ADD_JS_PROPERTY(env, object, value, createTime), object);
|
||||
NAPI_CALL_RETURN_ERR(ADD_JS_PROPERTY(env, object, value, modifyTime), object);
|
||||
NAPI_CALL_RETURN_ERR(ADD_JS_PROPERTY(env, object, value, size), object);
|
||||
NAPI_CALL_RETURN_ERR(ADD_JS_PROPERTY(env, object, value, path), 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(napi_set_named_property(env, object, "status", Convert2JSValue(env, outputStatus)), object);
|
||||
NAPI_CALL_RETURN_ERR(SetNamedProperty(env, object, "status", outputStatus), object);
|
||||
return object;
|
||||
}
|
||||
|
||||
template<>
|
||||
napi_value Convert2JSValue(napi_env env, const RowEntity &rowEntity)
|
||||
{
|
||||
napi_value ret = nullptr;
|
||||
NAPI_CALL(env, napi_create_object(env, &ret));
|
||||
napi_value object = nullptr;
|
||||
NAPI_CALL_RETURN_ERR(napi_create_object(env, &object), object);
|
||||
auto &values = rowEntity.Get();
|
||||
for (auto const &[key, object] : values) {
|
||||
napi_value value = JSUtils::Convert2JSValue(env, object);
|
||||
NAPI_CALL(env, napi_set_named_property(env, ret, key.c_str(), value));
|
||||
for (auto const &[key, value] : values) {
|
||||
NAPI_CALL_RETURN_ERR(SetNamedProperty(env, object, key.c_str(), value), object);
|
||||
}
|
||||
return ret;
|
||||
return object;
|
||||
}
|
||||
|
||||
template<>
|
||||
@ -142,37 +145,25 @@ napi_value Convert2JSValue(napi_env env, const ValueObject &valueObject)
|
||||
template<>
|
||||
napi_value Convert2JSValue(napi_env env, const DistributedRdb::Statistic &statistic)
|
||||
{
|
||||
napi_value jsValue = nullptr;
|
||||
napi_status status = napi_create_object(env, &jsValue);
|
||||
if (status != napi_ok) {
|
||||
return nullptr;
|
||||
}
|
||||
napi_value total = Convert2JSValue(env, statistic.total);
|
||||
napi_value success = Convert2JSValue(env, statistic.success);
|
||||
napi_value failed = Convert2JSValue(env, statistic.failed);
|
||||
napi_value untreated = Convert2JSValue(env, statistic.untreated);
|
||||
napi_value object = nullptr;
|
||||
NAPI_CALL_RETURN_ERR(napi_create_object(env, &object), object);
|
||||
|
||||
napi_set_named_property(env, jsValue, "total", total);
|
||||
napi_set_named_property(env, jsValue, "success", success);
|
||||
napi_set_named_property(env, jsValue, "successful", success);
|
||||
napi_set_named_property(env, jsValue, "failed", failed);
|
||||
napi_set_named_property(env, jsValue, "remained", untreated);
|
||||
return jsValue;
|
||||
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);
|
||||
return object;
|
||||
}
|
||||
|
||||
template<>
|
||||
napi_value Convert2JSValue(napi_env env, const DistributedRdb::TableDetail &tableDetail)
|
||||
{
|
||||
napi_value jsValue = nullptr;
|
||||
napi_status status = napi_create_object(env, &jsValue);
|
||||
if (status != napi_ok) {
|
||||
return nullptr;
|
||||
}
|
||||
napi_value upload = Convert2JSValue(env, tableDetail.upload);
|
||||
napi_value download = Convert2JSValue(env, tableDetail.download);
|
||||
napi_set_named_property(env, jsValue, "upload", upload);
|
||||
napi_set_named_property(env, jsValue, "download", download);
|
||||
return jsValue;
|
||||
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);
|
||||
return object;
|
||||
}
|
||||
|
||||
template<>
|
||||
@ -202,21 +193,19 @@ napi_value Convert2JSValue(napi_env env, const DistributedRdb::TableDetails &tab
|
||||
template<>
|
||||
napi_value Convert2JSValue(napi_env env, const DistributedRdb::ProgressDetail &progressDetail)
|
||||
{
|
||||
napi_value jsValue = nullptr;
|
||||
napi_status status = napi_create_object(env, &jsValue);
|
||||
if (status != napi_ok) {
|
||||
return nullptr;
|
||||
}
|
||||
napi_value object = nullptr;
|
||||
NAPI_CALL_RETURN_ERR(napi_create_object(env, &object), object);
|
||||
|
||||
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, jsValue, "schedule", schedule);
|
||||
napi_set_named_property(env, jsValue, "code", code);
|
||||
napi_set_named_property(env, jsValue, "details", details);
|
||||
return jsValue;
|
||||
napi_set_named_property(env, object, "schedule", schedule);
|
||||
napi_set_named_property(env, object, "code", code);
|
||||
napi_set_named_property(env, object, "details", details);
|
||||
return object;
|
||||
}
|
||||
|
||||
template<>
|
||||
@ -229,27 +218,21 @@ template<>
|
||||
napi_value Convert2JSValue(napi_env env, const JSChangeInfo &value)
|
||||
{
|
||||
napi_value object = nullptr;
|
||||
auto status = napi_create_object(env, &object);
|
||||
if (status != napi_ok) {
|
||||
return nullptr;
|
||||
}
|
||||
ADD_JS_PROPERTY(env, object, value, table);
|
||||
ADD_JS_PROPERTY(env, object, value, type);
|
||||
ADD_JS_PROPERTY(env, object, value, inserted);
|
||||
ADD_JS_PROPERTY(env, object, value, updated);
|
||||
ADD_JS_PROPERTY(env, object, value, deleted);
|
||||
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);
|
||||
return object;
|
||||
}
|
||||
|
||||
template<>
|
||||
napi_value Convert2JSValue(napi_env env, const Date &date)
|
||||
{
|
||||
napi_value jsValue = nullptr;
|
||||
napi_status status = napi_create_date(env, date, &jsValue);
|
||||
if (status != napi_ok) {
|
||||
return nullptr;
|
||||
}
|
||||
return jsValue;
|
||||
napi_value jsDeta = nullptr;
|
||||
NAPI_CALL_RETURN_ERR(napi_create_date(env, date, &jsDeta), jsDeta);
|
||||
return jsDeta;
|
||||
}
|
||||
|
||||
template<>
|
||||
@ -269,5 +252,173 @@ std::string ToString(const PRIKey &key)
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
bool IsNapiString(napi_env env, napi_value value)
|
||||
{
|
||||
napi_valuetype type = napi_undefined;
|
||||
NAPI_CALL_BASE(env, napi_typeof(env, value, &type), false);
|
||||
return type == napi_string;
|
||||
}
|
||||
|
||||
int32_t GetLevel(SecurityLevel level, SecurityLevel &out)
|
||||
{
|
||||
switch (level) {
|
||||
case SecurityLevel::S1:
|
||||
case SecurityLevel::S2:
|
||||
case SecurityLevel::S3:
|
||||
case SecurityLevel::S4:
|
||||
out = level;
|
||||
return napi_ok;
|
||||
default:
|
||||
return napi_invalid_arg;
|
||||
}
|
||||
}
|
||||
|
||||
template<>
|
||||
int32_t Convert2Value(napi_env env, napi_value jsValue, RdbConfig &rdbConfig)
|
||||
{
|
||||
int32_t status = GetNamedProperty(env, jsValue, "encrypt", rdbConfig.isEncrypt, true);
|
||||
ASSERT(OK == status, "get encrypt failed.", napi_invalid_arg);
|
||||
|
||||
int32_t securityLevel;
|
||||
status = GetNamedProperty(env, jsValue, "securityLevel", securityLevel);
|
||||
ASSERT(OK == status, "get securityLevel failed.", napi_invalid_arg);
|
||||
status = GetLevel(static_cast<SecurityLevel>(securityLevel), rdbConfig.securityLevel);
|
||||
ASSERT(status == napi_ok, "get securityLevel failed", status);
|
||||
|
||||
status = GetNamedProperty(env, jsValue, "dataGroupId", rdbConfig.dataGroupId, true);
|
||||
ASSERT(OK == status, "get dataGroupId failed.", napi_invalid_arg);
|
||||
|
||||
status = GetNamedProperty(env, jsValue, "autoCleanDirtyData", rdbConfig.isAutoClean, true);
|
||||
ASSERT(OK == status, "get autoCleanDirtyData failed.", napi_invalid_arg);
|
||||
|
||||
status = GetNamedProperty(env, jsValue, "name", rdbConfig.name);
|
||||
ASSERT(OK == status, "get name failed.", napi_invalid_arg);
|
||||
|
||||
status = GetNamedProperty(env, jsValue, "customDir", rdbConfig.customDir, true);
|
||||
ASSERT(OK == status, "get customDir failed.", napi_invalid_arg);
|
||||
|
||||
GetNamedProperty(env, jsValue, "isSearchable", rdbConfig.isSearchable, true);
|
||||
ASSERT(OK == status, "get isSearchable failed.", napi_invalid_arg);
|
||||
return napi_ok;
|
||||
}
|
||||
|
||||
int32_t GetCurrentAbilityParam(napi_env env, napi_value jsValue, ContextParam ¶m)
|
||||
{
|
||||
auto ability = AbilityRuntime::GetCurrentAbility(env);
|
||||
if (ability == nullptr) {
|
||||
LOG_ERROR("GetCurrentAbility failed.");
|
||||
return napi_invalid_arg;
|
||||
}
|
||||
auto abilityContext = ability->GetAbilityContext();
|
||||
if (abilityContext == nullptr) {
|
||||
LOG_ERROR("GetAbilityContext failed.");
|
||||
return napi_invalid_arg;
|
||||
}
|
||||
std::shared_ptr<Context> context = std::make_shared<Context>(abilityContext);
|
||||
param.baseDir = context->GetDatabaseDir();
|
||||
param.moduleName = context->GetModuleName();
|
||||
param.area = context->GetArea();
|
||||
param.bundleName = context->GetBundleName();
|
||||
param.isSystemApp = context->IsSystemAppCalled();
|
||||
return napi_ok;
|
||||
}
|
||||
|
||||
template<>
|
||||
int32_t Convert2Value(napi_env env, napi_value jsValue, ContextParam ¶m)
|
||||
{
|
||||
if (jsValue == nullptr) {
|
||||
LOG_INFO("hasProp is false -> fa stage");
|
||||
param.isStageMode = false;
|
||||
return GetCurrentAbilityParam(env, jsValue, param);
|
||||
}
|
||||
|
||||
int32_t status = GetNamedProperty(env, jsValue, "stageMode", param.isStageMode);
|
||||
ASSERT(status == napi_ok, "get stageMode param failed", napi_invalid_arg);
|
||||
if (!param.isStageMode) {
|
||||
LOG_WARN("isStageMode is false -> fa stage");
|
||||
return GetCurrentAbilityParam(env, jsValue, param);
|
||||
}
|
||||
LOG_DEBUG("stage mode branch");
|
||||
status = GetNamedProperty(env, jsValue, "databaseDir", param.baseDir);
|
||||
ASSERT(status == napi_ok, "get databaseDir failed.", napi_invalid_arg);
|
||||
status = GetNamedProperty(env, jsValue, "area", param.area);
|
||||
ASSERT(status == napi_ok, "get area failed.", napi_invalid_arg);
|
||||
|
||||
napi_value hapInfo = nullptr;
|
||||
GetNamedProperty(env, jsValue, "currentHapModuleInfo", hapInfo);
|
||||
if (hapInfo != nullptr) {
|
||||
status = GetNamedProperty(env, hapInfo, "name", param.moduleName);
|
||||
ASSERT(status == napi_ok, "get currentHapModuleInfo.name failed.", napi_invalid_arg);
|
||||
}
|
||||
|
||||
napi_value appInfo = nullptr;
|
||||
GetNamedProperty(env, jsValue, "applicationInfo", appInfo);
|
||||
if (appInfo != nullptr) {
|
||||
status = GetNamedProperty(env, appInfo, "name", param.bundleName);
|
||||
ASSERT(status == napi_ok, "get applicationInfo.name failed.", napi_invalid_arg);
|
||||
status = GetNamedProperty(env, appInfo, "systemApp", param.isSystemApp);
|
||||
ASSERT(status == napi_ok, "get applicationInfo.systemApp failed.", napi_invalid_arg);
|
||||
}
|
||||
return napi_ok;
|
||||
}
|
||||
|
||||
std::tuple<int32_t, std::shared_ptr<Error>> GetRealPath(
|
||||
napi_env env, napi_value jsValue, RdbConfig &rdbConfig, ContextParam ¶m)
|
||||
{
|
||||
CHECK_RETURN_CORE(rdbConfig.name.find(PATH_SPLIT) == std::string::npos, RDB_DO_NOTHING,
|
||||
std::make_tuple(ERR, std::make_shared<ParamError>("StoreConfig.name", "a file name without path.")));
|
||||
|
||||
if (!rdbConfig.customDir.empty()) {
|
||||
// determine if the first character of customDir is '/'
|
||||
CHECK_RETURN_CORE(rdbConfig.customDir.find_first_of(PATH_SPLIT) != 0, RDB_DO_NOTHING,
|
||||
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::string baseDir = param.baseDir;
|
||||
if (!rdbConfig.dataGroupId.empty()) {
|
||||
if (!param.isStageMode) {
|
||||
return std::make_tuple(ERR, std::make_shared<InnerError>(E_NOT_STAGE_MODE));
|
||||
}
|
||||
auto stageContext = AbilityRuntime::GetStageModeContext(env, jsValue);
|
||||
if (stageContext == nullptr) {
|
||||
return std::make_tuple(ERR, std::make_shared<ParamError>("Illegal context."));
|
||||
}
|
||||
std::string groupDir;
|
||||
int errCode = stageContext->GetSystemDatabaseDir(rdbConfig.dataGroupId, false, groupDir);
|
||||
CHECK_RETURN_CORE(errCode == E_OK || !groupDir.empty(), RDB_DO_NOTHING,
|
||||
std::make_tuple(ERR, std::make_shared<InnerError>(E_DATA_GROUP_ID_INVALID)));
|
||||
baseDir = groupDir;
|
||||
}
|
||||
|
||||
auto [realPath, errorCode] = RdbSqlUtils::GetDefaultDatabasePath(baseDir, rdbConfig.name, rdbConfig.customDir);
|
||||
// realPath length is limited to 1024 bytes
|
||||
CHECK_RETURN_CORE(errorCode == E_OK && realPath.length() <= 1024, RDB_DO_NOTHING,
|
||||
std::make_tuple(ERR, std::make_shared<ParamError>("database path", "a valid path.")));
|
||||
rdbConfig.path = realPath;
|
||||
return std::make_tuple(E_OK, nullptr);
|
||||
}
|
||||
|
||||
RdbStoreConfig GetRdbStoreConfig(const RdbConfig &rdbConfig, const ContextParam ¶m)
|
||||
{
|
||||
RdbStoreConfig rdbStoreConfig(rdbConfig.path);
|
||||
rdbStoreConfig.SetEncryptStatus(rdbConfig.isEncrypt);
|
||||
rdbStoreConfig.SetSearchable(rdbConfig.isSearchable);
|
||||
rdbStoreConfig.SetAutoClean(rdbConfig.isAutoClean);
|
||||
rdbStoreConfig.SetSecurityLevel(rdbConfig.securityLevel);
|
||||
rdbStoreConfig.SetDataGroupId(rdbConfig.dataGroupId);
|
||||
rdbStoreConfig.SetName(rdbConfig.name);
|
||||
rdbStoreConfig.SetCustomDir(rdbConfig.customDir);
|
||||
|
||||
if (!param.bundleName.empty()) {
|
||||
rdbStoreConfig.SetBundleName(param.bundleName);
|
||||
}
|
||||
rdbStoreConfig.SetModuleName(param.moduleName);
|
||||
rdbStoreConfig.SetArea(param.area);
|
||||
return rdbStoreConfig;
|
||||
}
|
||||
}; // namespace JSUtils
|
||||
} // namespace OHOS::AppDataMgrJsKit
|
@ -20,7 +20,9 @@
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
#include "js_native_api_types.h"
|
||||
#include "js_utils.h"
|
||||
#include "napi_rdb_js_utils.h"
|
||||
#include "logger.h"
|
||||
#include "napi_async_call.h"
|
||||
#include "napi_rdb_error.h"
|
||||
@ -38,6 +40,7 @@ using namespace OHOS::DataShare;
|
||||
using namespace OHOS::Rdb;
|
||||
using namespace OHOS::NativeRdb;
|
||||
using namespace OHOS::AppDataMgrJsKit;
|
||||
using namespace OHOS::AppDataMgrJsKit::JSUtils;
|
||||
|
||||
#if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM)
|
||||
using OHOS::DistributedRdb::SubscribeMode;
|
||||
@ -56,7 +59,7 @@ struct PredicatesProxy {
|
||||
std::shared_ptr<DataShareAbsPredicates> predicates_;
|
||||
};
|
||||
#endif
|
||||
struct RdbStoreContext : public Context {
|
||||
struct RdbStoreContext : public ContextBase {
|
||||
std::string device;
|
||||
std::string tableName;
|
||||
std::vector<std::string> tablesNames;
|
||||
@ -176,6 +179,8 @@ void RdbStoreProxy::Init(napi_env env, napi_value exports)
|
||||
DECLARE_NAPI_FUNCTION("commit", Commit),
|
||||
DECLARE_NAPI_FUNCTION("restore", Restore),
|
||||
DECLARE_NAPI_GETTER_SETTER("version", GetVersion, SetVersion),
|
||||
DECLARE_NAPI_FUNCTION("attach", Attach),
|
||||
DECLARE_NAPI_FUNCTION("detach", Detach),
|
||||
#if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM)
|
||||
DECLARE_NAPI_FUNCTION("remoteQuery", RemoteQuery),
|
||||
DECLARE_NAPI_FUNCTION("setDistributedTables", SetDistributedTables),
|
||||
@ -260,7 +265,7 @@ RdbStoreProxy *GetNativeInstance(napi_env env, napi_value self)
|
||||
return proxy;
|
||||
}
|
||||
|
||||
int ParserThis(const napi_env &env, const napi_value &self, std::shared_ptr<RdbStoreContext> context)
|
||||
int ParserThis(const napi_env &env, const napi_value &self, std::shared_ptr<ContextBase> context)
|
||||
{
|
||||
RdbStoreProxy *obj = GetNativeInstance(env, self);
|
||||
CHECK_RETURN_SET(obj && obj->rdbStore_, std::make_shared<ParamError>("RdbStore", "nullptr."));
|
||||
@ -882,23 +887,101 @@ napi_value RdbStoreProxy::Backup(napi_env env, napi_callback_info info)
|
||||
return AsyncCall::Call(env, context);
|
||||
}
|
||||
|
||||
struct AttachContext : public ContextBase {
|
||||
ContextParam param;
|
||||
RdbConfig config;
|
||||
std::string attachName;
|
||||
int32_t waitTime;
|
||||
int32_t attachedNum;
|
||||
};
|
||||
|
||||
napi_value RdbStoreProxy::Attach(napi_env env, napi_callback_info info)
|
||||
{
|
||||
auto context = std::make_shared<RdbStoreContext>();
|
||||
auto context = std::make_shared<AttachContext>();
|
||||
auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) {
|
||||
CHECK_RETURN_SET_E(argc == 3, std::make_shared<ParamNumError>("3 or 4"));
|
||||
CHECK_RETURN(OK == ParserThis(env, self, context));
|
||||
CHECK_RETURN(OK == ParseAlias(env, argv[0], context));
|
||||
CHECK_RETURN(OK == ParsePath(env, argv[1], context));
|
||||
int32_t errCode;
|
||||
// The parameter must be between 2 and 4
|
||||
CHECK_RETURN_SET_E(argc >= 2 && argc <= 4, std::make_shared<ParamNumError>("2 or 3 or 4"));
|
||||
// argv[0] may be a string or context.
|
||||
bool isString = IsNapiString(env, argv[0]);
|
||||
if (isString) {
|
||||
errCode = Convert2Value(env, argv[0], context->config.path);
|
||||
CHECK_RETURN_SET_E(napi_ok == errCode && !context->config.path.empty(),
|
||||
std::make_shared<ParamError>("fullPath cannot be empty."));
|
||||
} else {
|
||||
errCode = Convert2Value(env, argv[0], context->param);
|
||||
CHECK_RETURN_SET_E(OK == errCode, std::make_shared<ParamError>("Illegal context."));
|
||||
|
||||
int errCode = Convert2Value(env, argv[1], context->config);
|
||||
CHECK_RETURN_SET_E(OK == errCode, std::make_shared<ParamError>("Illegal StoreConfig or name."));
|
||||
|
||||
auto [code, err] = GetRealPath(env, argv[0], context->config, context->param);
|
||||
CHECK_RETURN_SET_E(OK == code, err);
|
||||
}
|
||||
// when the first parameter is string, the pos of attachName is 1; otherwise, it is 2
|
||||
size_t pos = isString ? 1 : 2;
|
||||
errCode = Convert2Value(env, argv[pos++], context->attachName);
|
||||
CHECK_RETURN_SET_E(napi_ok == errCode && !context->attachName.empty(),
|
||||
std::make_shared<ParamError>("attachName cannot be empty."));
|
||||
context->waitTime = WAIT_TIME_DEFAULT;
|
||||
if (pos < argc) {
|
||||
errCode = Convert2ValueExt(env, argv[pos], context->waitTime);
|
||||
CHECK_RETURN_SET_E(napi_ok == errCode && context->waitTime >= 1 && context->waitTime <= WAIT_TIME_LIMIT,
|
||||
std::make_shared<ParamError>("waitTime cannot exceed 300s."));
|
||||
}
|
||||
};
|
||||
auto exec = [context]() -> int {
|
||||
RdbStoreProxy *obj = reinterpret_cast<RdbStoreProxy *>(context->boundObj);
|
||||
CHECK_RETURN_ERR(obj != nullptr && obj->rdbStore_ != nullptr);
|
||||
return obj->rdbStore_->Attach(context->aliasName, context->pathName, context->newKey);
|
||||
auto res = obj->rdbStore_->Attach(
|
||||
GetRdbStoreConfig(context->config, context->param), context->attachName, context->waitTime);
|
||||
context->attachedNum = res.second;
|
||||
return res.first;
|
||||
};
|
||||
auto output = [context](napi_env env, napi_value &result) {
|
||||
napi_status status = napi_get_undefined(env, &result);
|
||||
CHECK_RETURN_SET_E(status == napi_ok, std::make_shared<InnerError>(E_ERROR));
|
||||
result = Convert2JSValue(env, context->attachedNum);
|
||||
CHECK_RETURN_SET_E(result != nullptr, std::make_shared<InnerError>(E_ERROR));
|
||||
};
|
||||
context->SetAction(env, info, input, exec, output);
|
||||
|
||||
CHECK_RETURN_NULL(context->error == nullptr || context->error->GetCode() == OK);
|
||||
return AsyncCall::Call(env, context);
|
||||
}
|
||||
|
||||
napi_value RdbStoreProxy::Detach(napi_env env, napi_callback_info info)
|
||||
{
|
||||
struct DetachContext : public ContextBase {
|
||||
std::string attachName;
|
||||
int32_t waitTime;
|
||||
int32_t attachedNum;
|
||||
};
|
||||
auto context = std::make_shared<DetachContext>();
|
||||
auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) {
|
||||
// this interface has 1 or 2 parameters
|
||||
CHECK_RETURN_SET_E(argc == 1 || argc == 2, std::make_shared<ParamNumError>("1 or 2"));
|
||||
CHECK_RETURN(OK == ParserThis(env, self, context));
|
||||
int32_t errCode = Convert2Value(env, argv[0], context->attachName);
|
||||
CHECK_RETURN_SET_E(napi_ok == errCode && !context->attachName.empty(),
|
||||
std::make_shared<ParamError>("attachName cannot be empty."));
|
||||
context->waitTime = WAIT_TIME_DEFAULT;
|
||||
// parse waitTime when the number of parameters is 2
|
||||
if (argc == 2) {
|
||||
errCode = Convert2ValueExt(env, argv[1], context->waitTime);
|
||||
CHECK_RETURN_SET_E(napi_ok == errCode && context->waitTime < WAIT_TIME_LIMIT,
|
||||
std::make_shared<ParamError>("waitTime cannot exceed 300s."));
|
||||
}
|
||||
};
|
||||
auto exec = [context]() -> int {
|
||||
RdbStoreProxy *obj = reinterpret_cast<RdbStoreProxy *>(context->boundObj);
|
||||
CHECK_RETURN_ERR(obj != nullptr && obj->rdbStore_ != nullptr);
|
||||
auto res = obj->rdbStore_->Detach(context->attachName, context->waitTime);
|
||||
context->attachedNum = res.second;
|
||||
return res.first;
|
||||
};
|
||||
auto output = [context](napi_env env, napi_value &result) {
|
||||
result = Convert2JSValue(env, context->attachedNum);
|
||||
CHECK_RETURN_SET_E(result != nullptr, std::make_shared<InnerError>(E_ERROR));
|
||||
};
|
||||
context->SetAction(env, info, input, exec, output);
|
||||
|
||||
|
@ -16,245 +16,28 @@
|
||||
#include "napi_rdb_store_helper.h"
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "js_ability.h"
|
||||
#include "js_utils.h"
|
||||
#include "logger.h"
|
||||
#include "napi_async_call.h"
|
||||
#include "napi_rdb_error.h"
|
||||
#include "napi_rdb_js_utils.h"
|
||||
#include "napi_rdb_store.h"
|
||||
#include "napi_rdb_trace.h"
|
||||
#include "rdb_errno.h"
|
||||
#include "rdb_open_callback.h"
|
||||
#include "rdb_sql_utils.h"
|
||||
#include "rdb_store_config.h"
|
||||
#include "unistd.h"
|
||||
|
||||
using namespace OHOS::Rdb;
|
||||
using namespace OHOS::NativeRdb;
|
||||
using namespace OHOS::AppDataMgrJsKit;
|
||||
using namespace OHOS::AppDataMgrJsKit::JSUtils;
|
||||
|
||||
namespace OHOS {
|
||||
namespace RelationalStoreJsKit {
|
||||
struct HelperRdbContext : public Context {
|
||||
RdbStoreConfig config;
|
||||
std::shared_ptr<RdbStore> proxy;
|
||||
std::shared_ptr<OHOS::AppDataMgrJsKit::Context> abilitycontext;
|
||||
bool isSystemAppCalled;
|
||||
|
||||
HelperRdbContext() : config(""), proxy(nullptr), isSystemAppCalled(false)
|
||||
{
|
||||
}
|
||||
virtual ~HelperRdbContext(){};
|
||||
};
|
||||
|
||||
int ParseContext(const napi_env &env, const napi_value &object, std::shared_ptr<HelperRdbContext> context)
|
||||
{
|
||||
napi_valuetype type = napi_undefined;
|
||||
napi_typeof(env, object, &type);
|
||||
CHECK_RETURN_SET(type == napi_object, std::make_shared<ParamError>("context", "object."));
|
||||
auto abilityContext = JSAbility::GetContext(env, object);
|
||||
CHECK_RETURN_SET(abilityContext != nullptr, std::make_shared<ParamError>("context", "a Context."));
|
||||
context->abilitycontext = abilityContext;
|
||||
return OK;
|
||||
}
|
||||
|
||||
int ParseIsEncrypt(const napi_env &env, const napi_value &object, std::shared_ptr<HelperRdbContext> context)
|
||||
{
|
||||
napi_value value = nullptr;
|
||||
napi_status status = napi_get_named_property(env, object, "encrypt", &value);
|
||||
if (status == napi_ok && value != nullptr) {
|
||||
bool isEncrypt = false;
|
||||
JSUtils::Convert2Value(env, value, isEncrypt);
|
||||
context->config.SetEncryptStatus(isEncrypt);
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
|
||||
int ParseIsSearchable(const napi_env &env, const napi_value &object, std::shared_ptr<HelperRdbContext> context)
|
||||
{
|
||||
napi_value value = nullptr;
|
||||
napi_status status = napi_get_named_property(env, object, "isSearchable", &value);
|
||||
if (status == napi_ok && value != nullptr) {
|
||||
bool isSearchable = false;
|
||||
auto status = JSUtils::Convert2Value(env, value, isSearchable);
|
||||
if (status != napi_ok) {
|
||||
return napi_invalid_arg;
|
||||
}
|
||||
context->config.SetSearchable(isSearchable);
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
|
||||
int ParseContextProperty(const napi_env &env, std::shared_ptr<HelperRdbContext> context)
|
||||
{
|
||||
context->config.SetModuleName(context->abilitycontext->GetModuleName());
|
||||
context->config.SetArea(context->abilitycontext->GetArea());
|
||||
context->config.SetBundleName(context->abilitycontext->GetBundleName());
|
||||
if (!context->abilitycontext->IsHasProxyDataConfig()) {
|
||||
context->config.SetUri(context->abilitycontext->GetUri());
|
||||
context->config.SetReadPermission(context->abilitycontext->GetReadPermission());
|
||||
context->config.SetWritePermission(context->abilitycontext->GetWritePermission());
|
||||
} else {
|
||||
context->config.SetUri("dataProxy");
|
||||
}
|
||||
context->isSystemAppCalled = context->abilitycontext->IsSystemAppCalled();
|
||||
return OK;
|
||||
}
|
||||
|
||||
int ParseDatabaseName(const napi_env &env, const napi_value &object, std::shared_ptr<HelperRdbContext> context)
|
||||
{
|
||||
napi_value value = nullptr;
|
||||
napi_get_named_property(env, object, "name", &value);
|
||||
CHECK_RETURN_SET(value != nullptr, std::make_shared<ParamError>("config", "a StoreConfig."));
|
||||
std::string databaseName = JSUtils::Convert2String(env, value);
|
||||
CHECK_RETURN_SET(!databaseName.empty(), std::make_shared<ParamError>("StoreConfig.name", "not empty."));
|
||||
if (databaseName.find("/") != std::string::npos) {
|
||||
CHECK_RETURN_SET(false, std::make_shared<ParamError>("StoreConfig.name", "a file name without path"));
|
||||
}
|
||||
context->config.SetName(databaseName);
|
||||
return OK;
|
||||
}
|
||||
|
||||
int ParseDatabasePath(const napi_env &env, const napi_value &object, std::shared_ptr<HelperRdbContext> context)
|
||||
{
|
||||
int errorCode = E_OK;
|
||||
|
||||
std::string defaultDir;
|
||||
if (context->config.GetDataGroupId().empty()) {
|
||||
defaultDir = context->abilitycontext->GetDatabaseDir();
|
||||
} else {
|
||||
errorCode = context->abilitycontext->GetSystemDatabaseDir(context->config.GetDataGroupId(), defaultDir);
|
||||
CHECK_RETURN_SET((errorCode == E_OK), std::make_shared<InnerError>(E_DATA_GROUP_ID_INVALID));
|
||||
}
|
||||
|
||||
bool hasProp = false;
|
||||
std::string customDir;
|
||||
napi_status status = napi_has_named_property(env, object, "customDir", &hasProp);
|
||||
if (status == napi_ok && hasProp) {
|
||||
napi_value value = nullptr;
|
||||
napi_get_named_property(env, object, "customDir", &value);
|
||||
CHECK_RETURN_SET(value != nullptr, std::make_shared<ParamError>("customDir", "a valid value."));
|
||||
JSUtils::Convert2Value(env, value, customDir);
|
||||
|
||||
size_t pos = customDir.find_first_of('/');
|
||||
// determine if the first character of customDir is '/'
|
||||
CHECK_RETURN_SET(pos != 0, std::make_shared<ParamError>("customDir", "a relative directory."));
|
||||
// customDir length is limited to 128 bytes
|
||||
CHECK_RETURN_SET(customDir.length() <= 128,
|
||||
std::make_shared<ParamError>("customDir length", "less than or equal to 128 bytes."));
|
||||
|
||||
context->config.SetCustomDir(customDir);
|
||||
}
|
||||
|
||||
auto [realPath, errCode] = RdbSqlUtils::GetDefaultDatabasePath(defaultDir, context->config.GetName(), customDir);
|
||||
// realPath length is limited to 1024 bytes
|
||||
CHECK_RETURN_SET(errCode == E_OK && realPath.length() <= 1024,
|
||||
std::make_shared<ParamError>("database path", "a valid path."));
|
||||
|
||||
context->config.SetPath(std::move(realPath));
|
||||
return OK;
|
||||
}
|
||||
|
||||
int ParseSecurityLevel(const napi_env &env, const napi_value &object, std::shared_ptr<HelperRdbContext> context)
|
||||
{
|
||||
napi_value value = nullptr;
|
||||
bool hasProp = false;
|
||||
napi_status status = napi_has_named_property(env, object, "securityLevel", &hasProp);
|
||||
CHECK_RETURN_SET(status == napi_ok && hasProp, std::make_shared<ParamError>("config", "with securityLevel."));
|
||||
|
||||
status = napi_get_named_property(env, object, "securityLevel", &value);
|
||||
CHECK_RETURN_SET(status == napi_ok, std::make_shared<ParamError>("config", "with securityLevel."));
|
||||
|
||||
int32_t securityLevel;
|
||||
napi_get_value_int32(env, value, &securityLevel);
|
||||
SecurityLevel sl = static_cast<SecurityLevel>(securityLevel);
|
||||
LOG_DEBUG("Get sl:%{public}d", securityLevel);
|
||||
|
||||
bool isValidSecurityLevel = sl >= SecurityLevel::S1 && sl < SecurityLevel::LAST;
|
||||
CHECK_RETURN_SET(isValidSecurityLevel, std::make_shared<ParamError>("config", "with correct securityLevel."));
|
||||
|
||||
context->config.SetSecurityLevel(sl);
|
||||
|
||||
LOG_DEBUG("ParseSecurityLevel end");
|
||||
return OK;
|
||||
}
|
||||
|
||||
int ParseDataGroupId(const napi_env &env, const napi_value &object, std::shared_ptr<HelperRdbContext> context)
|
||||
{
|
||||
bool hasProp = false;
|
||||
napi_status status = napi_has_named_property(env, object, "dataGroupId", &hasProp);
|
||||
if (status == napi_ok && hasProp) {
|
||||
napi_value value = nullptr;
|
||||
status = napi_get_named_property(env, object, "dataGroupId", &value);
|
||||
CHECK_RETURN_SET(status == napi_ok, std::make_shared<ParamError>("config", "with dataGroupId."));
|
||||
std::string dataGroupId = JSUtils::Convert2String(env, value);
|
||||
CHECK_RETURN_SET(!dataGroupId.empty(), std::make_shared<ParamError>
|
||||
("StoreConfig.dataGroupId", "not empty."));
|
||||
CHECK_RETURN_SET(context->abilitycontext->IsStageMode(), std::make_shared<InnerError>(E_NOT_STAGE_MODE));
|
||||
context->config.SetDataGroupId(JSUtils::Convert2String(env, value));
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
|
||||
int ParseAutoCleanDirtyData(const napi_env &env, const napi_value &object, std::shared_ptr<HelperRdbContext> context)
|
||||
{
|
||||
bool hasProp = false;
|
||||
napi_status status = napi_has_named_property(env, object, "autoCleanDirtyData", &hasProp);
|
||||
if (status == napi_ok && hasProp) {
|
||||
napi_value value = nullptr;
|
||||
status = napi_get_named_property(env, object, "autoCleanDirtyData", &value);
|
||||
CHECK_RETURN_SET(status == napi_ok, std::make_shared<ParamError>("config", "with autoCleanDirtyData."));
|
||||
bool isAutoClean = true;
|
||||
JSUtils::Convert2Value(env, value, isAutoClean);
|
||||
context->config.SetAutoClean(isAutoClean);
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
|
||||
int ParseStoreConfig(const napi_env &env, const napi_value &object, std::shared_ptr<HelperRdbContext> context)
|
||||
{
|
||||
CHECK_RETURN_CORE(OK == ParseIsEncrypt(env, object, context), RDB_REVT_NOTHING, ERR);
|
||||
CHECK_RETURN_CORE(OK == ParseSecurityLevel(env, object, context), RDB_REVT_NOTHING, ERR);
|
||||
CHECK_RETURN_CORE(OK == ParseDataGroupId(env, object, context), RDB_REVT_NOTHING, ERR);
|
||||
CHECK_RETURN_CORE(OK == ParseAutoCleanDirtyData(env, object, context), RDB_REVT_NOTHING, ERR);
|
||||
CHECK_RETURN_CORE(OK == ParseContextProperty(env, context), RDB_REVT_NOTHING, ERR);
|
||||
CHECK_RETURN_CORE(OK == ParseDatabaseName(env, object, context), RDB_REVT_NOTHING, ERR);
|
||||
CHECK_RETURN_CORE(OK == ParseDatabasePath(env, object, context), RDB_REVT_NOTHING, ERR);
|
||||
CHECK_RETURN_CORE(OK == ParseIsSearchable(env, object, context), RDB_REVT_NOTHING, ERR);
|
||||
return OK;
|
||||
}
|
||||
|
||||
int ParsePath(const napi_env env, const napi_value arg, std::shared_ptr<HelperRdbContext> context)
|
||||
{
|
||||
std::string path = JSUtils::Convert2String(env, arg);
|
||||
CHECK_RETURN_SET(!path.empty(), std::make_shared<ParamError>("name", "a without path non empty string."));
|
||||
|
||||
size_t pos = path.find_first_of('/');
|
||||
CHECK_RETURN_SET(pos == std::string::npos, std::make_shared<ParamError>("name", "a without path without /."));
|
||||
|
||||
CHECK_RETURN_SET(context->abilitycontext != nullptr,
|
||||
std::make_shared<ParamError>("abilitycontext", "abilitycontext is nullptr"));
|
||||
std::string defaultDir = context->abilitycontext->GetDatabaseDir();
|
||||
|
||||
int errorCode = E_OK;
|
||||
std::string realPath = RdbSqlUtils::GetDefaultDatabasePath(defaultDir, path, errorCode);
|
||||
CHECK_RETURN_SET(errorCode == E_OK, std::make_shared<ParamError>("config", "a StoreConfig."));
|
||||
|
||||
context->config.SetPath(realPath);
|
||||
return OK;
|
||||
}
|
||||
|
||||
bool IsNapiString(napi_env env, size_t argc, napi_value *argv, size_t arg)
|
||||
{
|
||||
if (arg >= argc) {
|
||||
return false;
|
||||
}
|
||||
napi_valuetype type = napi_undefined;
|
||||
NAPI_CALL_BASE(env, napi_typeof(env, argv[arg], &type), false);
|
||||
return type == napi_string;
|
||||
}
|
||||
using ContextParam = AppDataMgrJsKit::JSUtils::ContextParam;
|
||||
|
||||
class DefaultOpenCallback : public RdbOpenCallback {
|
||||
public:
|
||||
@ -270,20 +53,32 @@ public:
|
||||
|
||||
napi_value GetRdbStore(napi_env env, napi_callback_info info)
|
||||
{
|
||||
auto context = std::make_shared<HelperRdbContext>();
|
||||
struct DeleteContext : public ContextBase {
|
||||
ContextParam param;
|
||||
RdbConfig config;
|
||||
std::shared_ptr<RdbStore> proxy;
|
||||
};
|
||||
auto context = std::make_shared<DeleteContext>();
|
||||
auto input = [context, info](napi_env env, size_t argc, napi_value *argv, napi_value self) {
|
||||
CHECK_RETURN_SET_E(argc == 2, std::make_shared<ParamNumError>("2 or 3"));
|
||||
CHECK_RETURN(OK == ParseContext(env, argv[0], context));
|
||||
CHECK_RETURN(OK == ParseStoreConfig(env, argv[1], context));
|
||||
int errCode = Convert2Value(env, argv[0], context->param);
|
||||
CHECK_RETURN_SET_E(OK == errCode, std::make_shared<ParamError>("Illegal context."));
|
||||
|
||||
errCode = Convert2Value(env, argv[1], context->config);
|
||||
CHECK_RETURN_SET_E(OK == errCode, std::make_shared<ParamError>("Illegal StoreConfig or name."));
|
||||
|
||||
auto [code, err] = GetRealPath(env, argv[0], context->config, context->param);
|
||||
CHECK_RETURN_SET_E(OK == code, err);
|
||||
};
|
||||
auto exec = [context]() -> int {
|
||||
int errCode = OK;
|
||||
DefaultOpenCallback callback;
|
||||
context->proxy = RdbHelper::GetRdbStore(context->config, -1, callback, errCode);
|
||||
context->proxy =
|
||||
RdbHelper::GetRdbStore(GetRdbStoreConfig(context->config, context->param), -1, callback, errCode);
|
||||
return errCode;
|
||||
};
|
||||
auto output = [context](napi_env env, napi_value &result) {
|
||||
result = RdbStoreProxy::NewInstance(env, context->proxy, context->isSystemAppCalled);
|
||||
result = RdbStoreProxy::NewInstance(env, context->proxy, context->param.isSystemApp);
|
||||
CHECK_RETURN_SET_E(result != nullptr, std::make_shared<InnerError>(E_ERROR));
|
||||
};
|
||||
context->SetAction(env, info, input, exec, output);
|
||||
@ -294,18 +89,29 @@ napi_value GetRdbStore(napi_env env, napi_callback_info info)
|
||||
|
||||
napi_value DeleteRdbStore(napi_env env, napi_callback_info info)
|
||||
{
|
||||
auto context = std::make_shared<HelperRdbContext>();
|
||||
struct DeleteContext : public ContextBase {
|
||||
ContextParam param;
|
||||
RdbConfig config;
|
||||
};
|
||||
auto context = std::make_shared<DeleteContext>();
|
||||
auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) {
|
||||
CHECK_RETURN_SET_E(argc == 2, std::make_shared<ParamNumError>("2 or 3"));
|
||||
CHECK_RETURN(OK == ParseContext(env, argv[0], context));
|
||||
if (IsNapiString(env, argc, argv, 1)) {
|
||||
CHECK_RETURN(OK == ParsePath(env, argv[1], context));
|
||||
int errCode = Convert2Value(env, argv[0], context->param);
|
||||
CHECK_RETURN_SET_E(OK == errCode, std::make_shared<ParamError>("Illegal context."));
|
||||
|
||||
if (IsNapiString(env, argv[1])) {
|
||||
errCode = Convert2Value(env, argv[1], context->config.name);
|
||||
CHECK_RETURN_SET_E(OK == errCode, std::make_shared<ParamError>("Illegal path."));
|
||||
} else {
|
||||
CHECK_RETURN(OK == ParseStoreConfig(env, argv[1], context));
|
||||
errCode = Convert2Value(env, argv[1], context->config);
|
||||
CHECK_RETURN_SET_E(OK == errCode, std::make_shared<ParamError>("Illegal StoreConfig or name."));
|
||||
}
|
||||
|
||||
auto [code, err] = GetRealPath(env, argv[0], context->config, context->param);
|
||||
CHECK_RETURN_SET_E(OK == code, err);
|
||||
};
|
||||
auto exec = [context]() -> int {
|
||||
return RdbHelper::DeleteRdbStore(context->config.GetPath());
|
||||
return RdbHelper::DeleteRdbStore(context->config.path);
|
||||
};
|
||||
auto output = [context](napi_env env, napi_value &result) {
|
||||
napi_status status = napi_create_int64(env, OK, &result);
|
||||
|
@ -20,11 +20,13 @@
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <thread>
|
||||
#include <shared_mutex>
|
||||
#include <thread>
|
||||
|
||||
#include "dataobs_mgr_client.h"
|
||||
#include "concurrent_map.h"
|
||||
#include "data_ability_observer_stub.h"
|
||||
#include "dataobs_mgr_client.h"
|
||||
#include "rdb_errno.h"
|
||||
#include "rdb_service.h"
|
||||
#include "rdb_store.h"
|
||||
#include "rdb_store_config.h"
|
||||
@ -32,6 +34,7 @@
|
||||
#include "sqlite_connection_pool.h"
|
||||
#include "sqlite_statement.h"
|
||||
|
||||
|
||||
namespace OHOS {
|
||||
class ExecutorPool;
|
||||
}
|
||||
@ -112,8 +115,6 @@ public:
|
||||
int ExecuteForChangedRowCount(int64_t &outValue, const std::string &sql,
|
||||
const std::vector<ValueObject> &bindArgs) override;
|
||||
int Backup(const std::string databasePath, const std::vector<uint8_t> destEncryptKey) override;
|
||||
int Attach(const std::string &alias, const std::string &pathName,
|
||||
const std::vector<uint8_t> destEncryptKey) override;
|
||||
int GetVersion(int &version) override;
|
||||
int SetVersion(int version) override;
|
||||
int BeginTransaction() override;
|
||||
@ -172,6 +173,9 @@ public:
|
||||
std::vector<PRIKey>& keys) override;
|
||||
|
||||
int CleanDirtyData(const std::string &table, uint64_t cursor) override;
|
||||
std::pair<int32_t, int32_t> Attach(
|
||||
const RdbStoreConfig &config, const std::string &attachName, int32_t waitTime = 2) override;
|
||||
std::pair<int32_t, int32_t> Detach(const std::string &attachName, int32_t waitTime = 2) override;
|
||||
|
||||
private:
|
||||
using ExecuteSqls = std::vector<std::pair<std::string, std::vector<std::vector<ValueObject>>>>;
|
||||
@ -205,6 +209,8 @@ private:
|
||||
int RegisterDataChangeCallback();
|
||||
void InitDelayNotifier();
|
||||
bool ColHasSpecificField(const std::vector<std::string> &columns);
|
||||
int AttachInner(const std::string &attachName,
|
||||
const std::string &dbPath, const std::vector<uint8_t> &key, int32_t waitTime);
|
||||
|
||||
static constexpr char SCHEME_RDB[] = "rdb://";
|
||||
static constexpr uint32_t EXPANSION = 2;
|
||||
@ -236,6 +242,7 @@ private:
|
||||
std::shared_ptr<std::set<std::string>> syncTables_;
|
||||
std::map<std::string, std::list<std::shared_ptr<RdbStoreLocalObserver>>> localObservers_;
|
||||
std::map<std::string, std::list<sptr<RdbStoreLocalSharedObserver>>> localSharedObservers_;
|
||||
ConcurrentMap<std::string, const RdbStoreConfig> attachedInfo_;
|
||||
};
|
||||
} // namespace OHOS::NativeRdb
|
||||
#endif
|
||||
|
@ -62,18 +62,18 @@ public:
|
||||
int CleanDirtyData(const std::string &table, uint64_t cursor);
|
||||
int RegisterCallBackObserver(const DataChangeCallback &clientChangedData);
|
||||
int GetMaxVariableNumber();
|
||||
JournalMode GetJournalMode();
|
||||
private:
|
||||
static constexpr const char *MERGE_ASSETS_FUNC = "merge_assets";
|
||||
explicit SqliteConnection(bool isWriteConnection);
|
||||
int InnerOpen(const RdbStoreConfig &config, uint32_t retry);
|
||||
int GetDbPath(const RdbStoreConfig &config, std::string &dbPath);
|
||||
int Configure(const RdbStoreConfig &config, uint32_t retry, std::string &dbPath);
|
||||
int SetPageSize(const RdbStoreConfig &config);
|
||||
int SetEncryptKey(const RdbStoreConfig &config, uint32_t iter);
|
||||
int SetJournalMode(const RdbStoreConfig &config);
|
||||
int SetJournalSizeLimit(const RdbStoreConfig &config);
|
||||
int SetAutoCheckpoint(const RdbStoreConfig &config);
|
||||
int SetWalSyncMode(const std::string &syncMode);
|
||||
int SetSyncMode(const std::string &syncMode);
|
||||
int PrepareAndBind(const std::string &sql, const std::vector<ValueObject> &bindArgs);
|
||||
void LimitPermission(const std::string &dbPath) const;
|
||||
|
||||
@ -103,6 +103,7 @@ private:
|
||||
bool isConfigured_ = false;
|
||||
bool inTransaction_;
|
||||
bool hasClientObserver_ = false;
|
||||
JournalMode mode_ = JournalMode::MODE_WAL;
|
||||
int openFlags;
|
||||
int maxVariableNumber_;
|
||||
int32_t id_ = 0;
|
||||
|
@ -17,25 +17,31 @@
|
||||
#define NATIVE_RDB_SQLITE_CONNECTION_POOL_H
|
||||
|
||||
#include <condition_variable>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <vector>
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
#include <iterator>
|
||||
#include <stack>
|
||||
#include <list>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <sstream>
|
||||
#include <stack>
|
||||
|
||||
#include "base_transaction.h"
|
||||
#include "rdb_store_config.h"
|
||||
#include "sqlite_connection.h"
|
||||
#include "base_transaction.h"
|
||||
namespace OHOS {
|
||||
namespace NativeRdb {
|
||||
class SqliteConnectionPool : public std::enable_shared_from_this<SqliteConnectionPool> {
|
||||
public:
|
||||
using SharedConn = std::shared_ptr<SqliteConnection>;
|
||||
using SharedConns = std::vector<SharedConn>;
|
||||
static constexpr std::chrono::milliseconds INVALID_TIME = std::chrono::milliseconds(0);
|
||||
static constexpr int USE_COUNT_MAX = 2;
|
||||
static std::shared_ptr<SqliteConnectionPool> Create(const RdbStoreConfig &storeConfig, int &errCode);
|
||||
~SqliteConnectionPool();
|
||||
std::shared_ptr<SqliteConnection> AcquireConnection(bool isReadOnly);
|
||||
std::shared_ptr<SqliteConnection> AcquireByID(int32_t id);
|
||||
SharedConn AcquireConnection(bool isReadOnly);
|
||||
SharedConn Acquire(bool isReadOnly, std::chrono::milliseconds ms = INVALID_TIME);
|
||||
std::pair<SharedConn, SharedConns> AcquireAll(int32_t time);
|
||||
SharedConn AcquireByID(int32_t id);
|
||||
int RestartReaders();
|
||||
int ConfigLocale(const std::string &localeStr);
|
||||
int ChangeDbFileForRestore(const std::string &newPath, const std::string &backupPath,
|
||||
@ -44,10 +50,13 @@ public:
|
||||
std::mutex &GetTransactionStackMutex();
|
||||
int AcquireTransaction();
|
||||
void ReleaseTransaction();
|
||||
std::pair<int, SharedConn> DisableWalMode();
|
||||
int EnableWalMode();
|
||||
void CloseAllConnections();
|
||||
private:
|
||||
struct ConnNode {
|
||||
bool using_ = false;
|
||||
uint32_t tid_ = 0;
|
||||
int32_t tid_ = 0;
|
||||
int32_t id_ = 0;
|
||||
std::chrono::steady_clock::time_point time_ = std::chrono::steady_clock::now();
|
||||
std::shared_ptr<SqliteConnection> connect_;
|
||||
@ -71,9 +80,11 @@ private:
|
||||
std::mutex mutex_;
|
||||
std::condition_variable cond_;
|
||||
int32_t Initialize(int32_t max, int32_t timeout, Creator creator);
|
||||
std::pair<int32_t, std::shared_ptr<ConnNode>> Initialize(
|
||||
int32_t max, int32_t timeout, bool needAcquire, Creator creator);
|
||||
int32_t ConfigLocale(const std::string &locale);
|
||||
std::shared_ptr<ConnNode> Acquire();
|
||||
std::shared_ptr<ConnNode> AcquireById(int32_t id);
|
||||
std::shared_ptr<ConnNode> Acquire(std::chrono::milliseconds milliS);
|
||||
int32_t Release(std::shared_ptr<ConnNode> node);
|
||||
int32_t Clear();
|
||||
bool IsFull();
|
||||
@ -82,9 +93,8 @@ private:
|
||||
|
||||
explicit SqliteConnectionPool(const RdbStoreConfig &storeConfig);
|
||||
int Init();
|
||||
int32_t GetMaxReaders();
|
||||
int32_t GetMaxReaders(const RdbStoreConfig &config);
|
||||
void ReleaseNode(std::shared_ptr<ConnNode> node);
|
||||
void CloseAllConnections();
|
||||
|
||||
static constexpr int LIMITATION = 1024;
|
||||
RdbStoreConfig config_;
|
||||
|
@ -18,6 +18,8 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "rdb_store_config.h"
|
||||
|
||||
namespace OHOS {
|
||||
namespace NativeRdb {
|
||||
|
||||
@ -34,14 +36,15 @@ public:
|
||||
static constexpr int APP_DEFAULT_UMASK = 0002;
|
||||
static constexpr int SQLITE_MAX_COLUMN = 2000;
|
||||
static constexpr char ATTACH_BACKUP_SQL[] = "ATTACH ? AS backup KEY ?";
|
||||
static constexpr char ATTACH_SQL[] = "ATTACH ? AS ? KEY ?";
|
||||
static constexpr char ATTACH_SQL[] = "ATTACH DATABASE ? AS ? KEY ?";
|
||||
static constexpr char DETACH_SQL[] = "DETACH DATABASE ?";
|
||||
static constexpr char EXPORT_SQL[] = "SELECT export_database('backup')";
|
||||
static constexpr char DETACH_BACKUP_SQL[] = "detach backup";
|
||||
static constexpr char PRAGMA_JOUR_MODE_EXP[] = "PRAGMA journal_mode";
|
||||
static constexpr char PRAGMA_VERSION[] = "PRAGMA user_version";
|
||||
static constexpr char DEFAULT_JOURNAL_MODE[] = "WAL";
|
||||
static constexpr char DB_DEFAULT_JOURNAL_MODE[] = "DELETE";
|
||||
static constexpr char WAL_SYNC_MODE[] = "FULL";
|
||||
static constexpr char JOURNAL_MODE_WAL[] = "WAL";
|
||||
static constexpr char JOURNAL_MODE_DELETE[] = "DELETE";
|
||||
static constexpr char DEFAULE_SYNC_MODE[] = "FULL";
|
||||
static constexpr char MEMORY_DB_PATH[] = ":memory:";
|
||||
static constexpr char ENCRYPT_ALGO[] = "sha256";
|
||||
static constexpr char CODEC_HMAC_ALGO[] = "PRAGMA codec_hmac_algo=sha256";
|
||||
@ -60,10 +63,11 @@ public:
|
||||
static int GetReadConnectionCount();
|
||||
static std::string GetMemoryDbPath();
|
||||
static int GetPageSize();
|
||||
static std::string GetWalSyncMode();
|
||||
static std::string GetSyncMode();
|
||||
static int GetJournalFileSize();
|
||||
static int GetWalAutoCheckpoint();
|
||||
static std::string GetDefaultJournalMode();
|
||||
static int GetDbPath(const RdbStoreConfig &config, std::string &dbPath);
|
||||
};
|
||||
|
||||
} // namespace NativeRdb
|
||||
|
@ -22,11 +22,13 @@
|
||||
#include <mutex>
|
||||
#include <thread>
|
||||
|
||||
#include "concurrent_map.h"
|
||||
#include "rdb_store.h"
|
||||
#include "rdb_store_config.h"
|
||||
#include "sqlite_connection_pool.h"
|
||||
#include "sqlite_statement.h"
|
||||
|
||||
|
||||
namespace OHOS::NativeRdb {
|
||||
class RdbStoreImpl : public RdbStore, public std::enable_shared_from_this<RdbStoreImpl> {
|
||||
public:
|
||||
@ -65,8 +67,6 @@ public:
|
||||
int ExecuteForChangedRowCount(int64_t &outValue, const std::string &sql,
|
||||
const std::vector<ValueObject> &bindArgs) override;
|
||||
int Backup(const std::string databasePath, const std::vector<uint8_t> destEncryptKey) override;
|
||||
int Attach(const std::string &alias, const std::string &pathName,
|
||||
const std::vector<uint8_t> destEncryptKey) override;
|
||||
int GetVersion(int &version) override;
|
||||
int SetVersion(int version) override;
|
||||
int BeginTransaction() override;
|
||||
@ -91,6 +91,9 @@ public:
|
||||
int Count(int64_t &outValue, const AbsRdbPredicates &predicates) override;
|
||||
int Update(int &changedRows, const ValuesBucket &values, const AbsRdbPredicates &predicates) override;
|
||||
int Delete(int &deletedRows, const AbsRdbPredicates &predicates) override;
|
||||
std::pair<int32_t, int32_t> Attach(
|
||||
const RdbStoreConfig &config, const std::string &attachName, int32_t waitTime = 2) override;
|
||||
std::pair<int32_t, int32_t> Detach(const std::string &attachName, int32_t waitTime = 2) override;
|
||||
|
||||
private:
|
||||
using ExecuteSqls = std::vector<std::pair<std::string, std::vector<std::vector<ValueObject>>>>;
|
||||
@ -111,6 +114,8 @@ private:
|
||||
const std::vector<uint8_t> &destEncryptKey = std::vector<uint8_t>());
|
||||
inline std::string GetSqlArgs(size_t size);
|
||||
int RegisterDataChangeCallback();
|
||||
int AttachInner(const std::string &attachName,
|
||||
const std::string &dbPath, const std::vector<uint8_t> &key, int32_t waitTime);
|
||||
|
||||
static constexpr char SCHEME_RDB[] = "rdb://";
|
||||
static constexpr uint32_t EXPANSION = 2;
|
||||
@ -120,6 +125,7 @@ private:
|
||||
|
||||
const RdbStoreConfig config_;
|
||||
std::shared_ptr<SqliteConnectionPool> connectionPool_;
|
||||
ConcurrentMap<std::string, const RdbStoreConfig> attachedInfo_;
|
||||
bool isOpen_ = false;
|
||||
bool isReadOnly_;
|
||||
bool isMemoryRdb_;
|
||||
|
@ -63,6 +63,7 @@ public:
|
||||
int GetMaxVariableNumber();
|
||||
int32_t GetId() const;
|
||||
int32_t SetId(int32_t id);
|
||||
JournalMode GetJournalMode();
|
||||
private:
|
||||
static constexpr const char *MERGE_ASSETS_FUNC = "merge_assets";
|
||||
explicit SqliteConnection(bool isWriteConnection);
|
||||
@ -74,7 +75,7 @@ private:
|
||||
int SetJournalMode(const RdbStoreConfig &config);
|
||||
int SetJournalSizeLimit(const RdbStoreConfig &config);
|
||||
int SetAutoCheckpoint(const RdbStoreConfig &config);
|
||||
int SetWalSyncMode(const std::string &syncMode);
|
||||
int SetSyncMode(const std::string &syncMode);
|
||||
int PrepareAndBind(const std::string &sql, const std::vector<ValueObject> &bindArgs);
|
||||
void LimitPermission(const std::string &dbPath) const;
|
||||
|
||||
@ -102,6 +103,7 @@ private:
|
||||
bool isConfigured_ = false;
|
||||
bool inTransaction_;
|
||||
bool hasClientObserver_ = false;
|
||||
JournalMode mode_ = JournalMode::MODE_WAL;
|
||||
int openFlags;
|
||||
int maxVariableNumber_;
|
||||
int32_t id_ = 0;
|
||||
|
@ -17,24 +17,32 @@
|
||||
#define NATIVE_RDB_SQLITE_CONNECTION_POOL_H
|
||||
|
||||
#include <condition_variable>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <vector>
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
#include <iterator>
|
||||
#include <stack>
|
||||
#include <list>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <sstream>
|
||||
#include <stack>
|
||||
#include <vector>
|
||||
|
||||
#include "base_transaction.h"
|
||||
#include "rdb_store_config.h"
|
||||
#include "sqlite_connection.h"
|
||||
#include "base_transaction.h"
|
||||
namespace OHOS {
|
||||
namespace NativeRdb {
|
||||
class SqliteConnectionPool : public std::enable_shared_from_this<SqliteConnectionPool> {
|
||||
public:
|
||||
using SharedConn = std::shared_ptr<SqliteConnection>;
|
||||
using SharedConns = std::vector<SharedConn>;
|
||||
static constexpr std::chrono::milliseconds INVALID_TIME = std::chrono::milliseconds(0);
|
||||
static constexpr int USE_COUNT_MAX = 2;
|
||||
static std::shared_ptr<SqliteConnectionPool> Create(const RdbStoreConfig &storeConfig, int &errCode);
|
||||
~SqliteConnectionPool();
|
||||
std::shared_ptr<SqliteConnection> AcquireConnection(bool isReadOnly);
|
||||
SharedConn AcquireConnection(bool isReadOnly);
|
||||
SharedConn Acquire(bool isReadOnly, std::chrono::milliseconds ms = INVALID_TIME);
|
||||
std::pair<SharedConn, SharedConns> AcquireAll(int32_t time);
|
||||
SharedConn AcquireByID(int32_t id);
|
||||
int RestartReaders();
|
||||
int ConfigLocale(const std::string &localeStr);
|
||||
int ChangeDbFileForRestore(const std::string &newPath, const std::string &backupPath,
|
||||
@ -43,12 +51,14 @@ public:
|
||||
std::mutex &GetTransactionStackMutex();
|
||||
int AcquireTransaction();
|
||||
void ReleaseTransaction();
|
||||
std::shared_ptr<SqliteConnection> AcquireByID(int32_t id);
|
||||
std::pair<int, std::shared_ptr<SqliteConnection>> DisableWalMode();
|
||||
int EnableWalMode();
|
||||
void CloseAllConnections();
|
||||
private:
|
||||
struct ConnNode {
|
||||
bool using_ = false;
|
||||
uint32_t tid_ = 0;
|
||||
uint32_t id_ = 0;
|
||||
int32_t tid_ = 0;
|
||||
int32_t id_ = 0;
|
||||
std::chrono::steady_clock::time_point time_ = std::chrono::steady_clock::now();
|
||||
std::shared_ptr<SqliteConnection> connect_;
|
||||
|
||||
@ -63,28 +73,29 @@ private:
|
||||
using Creator = std::function<std::pair<int32_t, std::shared_ptr<SqliteConnection>>()>;
|
||||
int max_ = 0;
|
||||
int count_ = 0;
|
||||
uint32_t left_ = 0;
|
||||
uint32_t right_ = 0;
|
||||
int32_t left_ = 0;
|
||||
int32_t right_ = 0;
|
||||
std::chrono::seconds timeout_;
|
||||
std::list<std::shared_ptr<ConnNode>> nodes_;
|
||||
std::list<std::weak_ptr<ConnNode>> details_;
|
||||
std::mutex mutex_;
|
||||
std::condition_variable cond_;
|
||||
int32_t Initialize(int32_t max, int32_t timeout, Creator creator);
|
||||
std::pair<int32_t, std::shared_ptr<ConnNode>> Initialize(
|
||||
int32_t max, int32_t timeout, bool needAcquire, Creator creator);
|
||||
int32_t ConfigLocale(const std::string &locale);
|
||||
std::shared_ptr<ConnNode> Acquire();
|
||||
std::shared_ptr<SqliteConnectionPool::ConnNode> AcquireById(int32_t id);
|
||||
std::shared_ptr<ConnNode> Acquire(std::chrono::milliseconds milliS);
|
||||
int32_t Release(std::shared_ptr<ConnNode> node);
|
||||
int32_t Clear();
|
||||
bool IsFull();
|
||||
int32_t Dump(const char *header);
|
||||
std::shared_ptr<SqliteConnectionPool::ConnNode> AcquireById(int32_t id);
|
||||
};
|
||||
|
||||
explicit SqliteConnectionPool(const RdbStoreConfig &storeConfig);
|
||||
int Init();
|
||||
int32_t GetMaxReaders();
|
||||
int32_t GetMaxReaders(const RdbStoreConfig &config);
|
||||
void ReleaseNode(std::shared_ptr<ConnNode> node);
|
||||
void CloseAllConnections();
|
||||
|
||||
static constexpr int LIMITATION = 1024;
|
||||
RdbStoreConfig config_;
|
||||
|
@ -54,7 +54,7 @@ int RdbHelper::DeleteRdbStore(const std::string &dbFileName)
|
||||
{
|
||||
DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__));
|
||||
if (dbFileName.empty()) {
|
||||
return E_EMPTY_FILE_NAME;
|
||||
return E_INVALID_FILE_PATH;
|
||||
}
|
||||
if (access(dbFileName.c_str(), F_OK) != 0) {
|
||||
return E_OK; // not not exist
|
||||
|
@ -42,6 +42,10 @@ RdbStoreConfig::RdbStoreConfig(const std::string &name, StorageMode storageMode,
|
||||
{
|
||||
}
|
||||
|
||||
RdbStoreConfig::RdbStoreConfig()
|
||||
{
|
||||
}
|
||||
|
||||
RdbStoreConfig::~RdbStoreConfig()
|
||||
{
|
||||
ClearEncryptKey();
|
||||
|
@ -1014,33 +1014,36 @@ int RdbStoreImpl::InnerBackup(const std::string &databasePath, const std::vector
|
||||
if (config_.GetRoleType() == VISITOR) {
|
||||
return E_NOT_SUPPORT;
|
||||
}
|
||||
|
||||
auto conn = connectionPool_->AcquireConnection(true);
|
||||
if (conn == nullptr) {
|
||||
return E_BASE;
|
||||
}
|
||||
std::vector<ValueObject> bindArgs;
|
||||
bindArgs.emplace_back(databasePath);
|
||||
if (!destEncryptKey.empty() && !isEncrypt_) {
|
||||
bindArgs.emplace_back(destEncryptKey);
|
||||
(static_cast<RdbStore *>(this))->ExecuteSql(GlobalExpr::CIPHER_DEFAULT_ATTACH_HMAC_ALGO);
|
||||
conn->ExecuteSql(GlobalExpr::CIPHER_DEFAULT_ATTACH_HMAC_ALGO);
|
||||
#if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM)
|
||||
} else if (isEncrypt_) {
|
||||
RdbPassword rdbPwd = RdbSecurityManager::GetInstance().GetRdbPassword(
|
||||
config_.GetPath(), RdbSecurityManager::KeyFileType::PUB_KEY_FILE);
|
||||
std::vector<uint8_t> key = std::vector<uint8_t>(rdbPwd.GetData(), rdbPwd.GetData() + rdbPwd.GetSize());
|
||||
bindArgs.emplace_back(key);
|
||||
(static_cast<RdbStore *>(this))->ExecuteSql(GlobalExpr::CIPHER_DEFAULT_ATTACH_HMAC_ALGO);
|
||||
conn->ExecuteSql(GlobalExpr::CIPHER_DEFAULT_ATTACH_HMAC_ALGO);
|
||||
#endif
|
||||
} else {
|
||||
std::string str = "";
|
||||
bindArgs.emplace_back(str);
|
||||
}
|
||||
|
||||
int ret = ExecuteSqlInner(GlobalExpr::ATTACH_BACKUP_SQL, bindArgs);
|
||||
int ret = conn->ExecuteSql(GlobalExpr::ATTACH_BACKUP_SQL, bindArgs);
|
||||
if (ret != E_OK) {
|
||||
return ret;
|
||||
}
|
||||
int64_t count;
|
||||
ret = conn->ExecuteGetLong(count, GlobalExpr::EXPORT_SQL, std::vector<ValueObject>());
|
||||
|
||||
ret = ExecuteGetLongInner(GlobalExpr::EXPORT_SQL, std::vector<ValueObject>());
|
||||
|
||||
int res = ExecuteSqlInner(GlobalExpr::DETACH_BACKUP_SQL, std::vector<ValueObject>());
|
||||
int res = conn->ExecuteSql(GlobalExpr::DETACH_BACKUP_SQL, std::vector<ValueObject>());
|
||||
|
||||
return res == E_OK ? ret : res;
|
||||
}
|
||||
@ -1085,57 +1088,122 @@ bool RdbStoreImpl::IsHoldingConnection()
|
||||
return connectionPool_ != nullptr;
|
||||
}
|
||||
|
||||
int RdbStoreImpl::AttachInner(
|
||||
const std::string &attachName, const std::string &dbPath, const std::vector<uint8_t> &key, int32_t waitTime)
|
||||
{
|
||||
auto [conn, readers] = connectionPool_->AcquireAll(waitTime);
|
||||
if (conn == nullptr) {
|
||||
return E_DATABASE_BUSY;
|
||||
}
|
||||
|
||||
if (conn->GetJournalMode() == JournalMode::MODE_WAL) {
|
||||
// close first to prevent the connection from being put back.
|
||||
connectionPool_->CloseAllConnections();
|
||||
conn = nullptr;
|
||||
readers.clear();
|
||||
auto [err, newConn] = connectionPool_->DisableWalMode();
|
||||
if (err != E_OK) {
|
||||
return err;
|
||||
}
|
||||
conn = newConn;
|
||||
}
|
||||
std::vector<ValueObject> bindArgs;
|
||||
bindArgs.emplace_back(ValueObject(dbPath));
|
||||
bindArgs.emplace_back(ValueObject(attachName));
|
||||
if (!key.empty()) {
|
||||
conn->ExecuteSql(GlobalExpr::CIPHER_DEFAULT_ATTACH_HMAC_ALGO);
|
||||
bindArgs.emplace_back(ValueObject(key));
|
||||
}
|
||||
return conn->ExecuteSql(GlobalExpr::ATTACH_SQL, bindArgs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Attaches a database.
|
||||
*/
|
||||
int RdbStoreImpl::Attach(const std::string &alias, const std::string &pathName,
|
||||
const std::vector<uint8_t> destEncryptKey)
|
||||
std::pair<int32_t, int32_t> RdbStoreImpl::Attach(
|
||||
const RdbStoreConfig &config, const std::string &attachName, int32_t waitTime)
|
||||
{
|
||||
std::shared_ptr<SqliteConnection> connection;
|
||||
std::string sql = GlobalExpr::PRAGMA_JOUR_MODE_EXP;
|
||||
int errCode = BeginExecuteSql(sql, connection);
|
||||
if (errCode != 0) {
|
||||
return errCode;
|
||||
if (config_.GetRoleType() == VISITOR) {
|
||||
return { E_NOT_SUPPORT, 0 };
|
||||
}
|
||||
std::string journalMode;
|
||||
errCode = connection->ExecuteGetString(journalMode, sql, std::vector<ValueObject>());
|
||||
if (errCode != E_OK) {
|
||||
LOG_ERROR("RdbStoreImpl CheckAttach fail to get journal mode : %d", errCode);
|
||||
return errCode;
|
||||
}
|
||||
journalMode = SqliteUtils::StrToUpper(journalMode);
|
||||
if (journalMode == GlobalExpr::DEFAULT_JOURNAL_MODE) {
|
||||
LOG_ERROR("RdbStoreImpl attach is not supported in WAL mode");
|
||||
return E_NOT_SUPPORTED_ATTACH_IN_WAL_MODE;
|
||||
std::string dbPath;
|
||||
int err = SqliteGlobalConfig::GetDbPath(config, dbPath);
|
||||
if (err != E_OK || access(dbPath.c_str(), F_OK) != E_OK) {
|
||||
return { E_INVALID_FILE_PATH, 0 };
|
||||
}
|
||||
|
||||
std::vector<ValueObject> bindArgs;
|
||||
bindArgs.emplace_back(pathName);
|
||||
bindArgs.emplace_back(alias);
|
||||
if (!destEncryptKey.empty() && !isEncrypt_) {
|
||||
bindArgs.emplace_back(destEncryptKey);
|
||||
(static_cast<RdbStore *>(this))->ExecuteSql(GlobalExpr::CIPHER_DEFAULT_ATTACH_HMAC_ALGO);
|
||||
// encrypted databases are not supported to attach a non encrypted database.
|
||||
if (!config.IsEncrypt() && isEncrypt_) {
|
||||
return { E_NOT_SUPPORTED, 0 };
|
||||
}
|
||||
|
||||
auto iter = attachedInfo_.Find(attachName);
|
||||
if (iter.first) {
|
||||
return { E_ATTACHED_DATABASE_EXIST, 0 };
|
||||
}
|
||||
|
||||
std::vector<uint8_t> key;
|
||||
#if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM)
|
||||
} else if (isEncrypt_) {
|
||||
if (config.IsEncrypt()) {
|
||||
RdbPassword rdbPwd =
|
||||
RdbSecurityManager::GetInstance().GetRdbPassword(config_.GetPath(),
|
||||
RdbSecurityManager::KeyFileType::PUB_KEY_FILE);
|
||||
std::vector<uint8_t> key = std::vector<uint8_t>(rdbPwd.GetData(), rdbPwd.GetData() + rdbPwd.GetSize());
|
||||
bindArgs.emplace_back(key);
|
||||
(static_cast<RdbStore *>(this))->ExecuteSql(GlobalExpr::CIPHER_DEFAULT_ATTACH_HMAC_ALGO);
|
||||
#endif
|
||||
} else {
|
||||
std::string str = "";
|
||||
bindArgs.push_back(ValueObject(str));
|
||||
RdbSecurityManager::GetInstance().GetRdbPassword(dbPath, RdbSecurityManager::KeyFileType::PUB_KEY_FILE);
|
||||
key = std::vector<uint8_t>(rdbPwd.GetData(), rdbPwd.GetData() + rdbPwd.GetSize());
|
||||
}
|
||||
sql = GlobalExpr::ATTACH_SQL;
|
||||
errCode = connection->ExecuteSql(sql, bindArgs);
|
||||
if (errCode != E_OK) {
|
||||
LOG_ERROR("ExecuteSql ATTACH_SQL error %d", errCode);
|
||||
#endif
|
||||
err = AttachInner(attachName, dbPath, key, waitTime);
|
||||
if (err == SQLITE_ERROR) {
|
||||
// only when attachName is already in use, SQLITE-ERROR will be reported here.
|
||||
return { E_ATTACHED_DATABASE_EXIST, 0 };
|
||||
} else if (err != E_OK) {
|
||||
LOG_ERROR("failed, errCode[%{public}d] fileName[%{public}s] attachName[%{public}s] attach fileName"
|
||||
"[%{public}s]",
|
||||
err, config_.GetName().c_str(), attachName.c_str(), config.GetName().c_str());
|
||||
return { err, 0 };
|
||||
}
|
||||
if (!attachedInfo_.Insert(attachName, config)) {
|
||||
return { E_ATTACHED_DATABASE_EXIST, 0 };
|
||||
}
|
||||
return { E_OK, attachedInfo_.Size() };
|
||||
}
|
||||
|
||||
std::pair<int32_t, int32_t> RdbStoreImpl::Detach(const std::string &attachName, int32_t waitTime)
|
||||
{
|
||||
if (config_.GetRoleType() == VISITOR) {
|
||||
return { E_NOT_SUPPORT, 0 };
|
||||
}
|
||||
auto iter = attachedInfo_.Find(attachName);
|
||||
if (!iter.first) {
|
||||
return { E_OK, attachedInfo_.Size() };
|
||||
}
|
||||
|
||||
return errCode;
|
||||
auto [connection, readers] = connectionPool_->AcquireAll(waitTime);
|
||||
if (connection == nullptr) {
|
||||
return { E_DATABASE_BUSY, 0 };
|
||||
}
|
||||
std::vector<ValueObject> bindArgs;
|
||||
bindArgs.push_back(ValueObject(attachName));
|
||||
|
||||
int err = connection->ExecuteSql(GlobalExpr::DETACH_SQL, bindArgs);
|
||||
if (err != E_OK) {
|
||||
LOG_ERROR("failed, errCode[%{public}d] fileName[%{public}s] attachName[%{public}s] attach fileName"
|
||||
"[%{public}s]",
|
||||
err, config_.GetName().c_str(), attachName.c_str(), iter.second.GetName().c_str());
|
||||
return { err, 0 };
|
||||
}
|
||||
|
||||
attachedInfo_.Erase(attachName);
|
||||
if (!attachedInfo_.Empty()) {
|
||||
return { E_OK, attachedInfo_.Size() };
|
||||
}
|
||||
// close first to prevent the connection from being put back.
|
||||
connectionPool_->CloseAllConnections();
|
||||
connection = nullptr;
|
||||
readers.clear();
|
||||
err = connectionPool_->EnableWalMode();
|
||||
if (err != E_OK) {
|
||||
return { err, 0 };
|
||||
}
|
||||
return { E_OK, 0 };
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1338,7 +1406,7 @@ int RdbStoreImpl::CheckAttach(const std::string &sql)
|
||||
}
|
||||
|
||||
journalMode = SqliteUtils::StrToUpper(journalMode);
|
||||
if (journalMode == GlobalExpr::DEFAULT_JOURNAL_MODE) {
|
||||
if (journalMode == GlobalExpr::JOURNAL_MODE_WAL) {
|
||||
LOG_ERROR("RdbStoreImpl attach is not supported in WAL mode");
|
||||
return E_NOT_SUPPORTED_ATTACH_IN_WAL_MODE;
|
||||
}
|
||||
@ -1910,5 +1978,6 @@ bool RdbStoreImpl::ColHasSpecificField(const std::vector<std::string> &columns)
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif
|
||||
} // namespace OHOS::NativeRdb
|
@ -17,6 +17,7 @@
|
||||
|
||||
#include <sqlite3sym.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <cerrno>
|
||||
#include <memory>
|
||||
@ -83,38 +84,10 @@ SqliteConnection::SqliteConnection(bool isWriteConnection)
|
||||
{
|
||||
}
|
||||
|
||||
int SqliteConnection::GetDbPath(const RdbStoreConfig &config, std::string &dbPath)
|
||||
{
|
||||
std::string path;
|
||||
if (config.GetRoleType() == VISITOR) {
|
||||
path = config.GetVisitorDir();
|
||||
} else {
|
||||
path = config.GetPath();
|
||||
}
|
||||
|
||||
if (config.GetStorageMode() == StorageMode::MODE_MEMORY) {
|
||||
if (config.GetRoleType() == VISITOR) {
|
||||
LOG_ERROR("not support MODE_MEMORY, storeName:%{public}s, role:%{public}d", config.GetName().c_str(),
|
||||
config.GetRoleType());
|
||||
return E_NOT_SUPPORT;
|
||||
}
|
||||
dbPath = SqliteGlobalConfig::GetMemoryDbPath();
|
||||
} else if (path.empty()) {
|
||||
LOG_ERROR("SqliteConnection GetDbPath input empty database path");
|
||||
return E_EMPTY_FILE_NAME;
|
||||
} else if (path.front() != '/' && path.at(1) != ':') {
|
||||
LOG_ERROR("SqliteConnection GetDbPath input relative path");
|
||||
return E_RELATIVE_PATH;
|
||||
} else {
|
||||
dbPath = path;
|
||||
}
|
||||
return E_OK;
|
||||
}
|
||||
|
||||
int SqliteConnection::InnerOpen(const RdbStoreConfig &config, uint32_t retry)
|
||||
{
|
||||
std::string dbPath;
|
||||
auto ret = GetDbPath(config, dbPath);
|
||||
auto ret = SqliteGlobalConfig::GetDbPath(config, dbPath);
|
||||
if (ret != E_OK) {
|
||||
return ret;
|
||||
}
|
||||
@ -478,10 +451,9 @@ int SqliteConnection::RegDefaultFunctions(sqlite3 *dbHandle)
|
||||
|
||||
int SqliteConnection::SetJournalMode(const RdbStoreConfig &config)
|
||||
{
|
||||
if (isReadOnly || config.GetJournalMode().compare(GlobalExpr::DB_DEFAULT_JOURNAL_MODE) == 0) {
|
||||
if (isReadOnly) {
|
||||
return E_OK;
|
||||
}
|
||||
|
||||
std::string currentMode;
|
||||
int errCode = ExecuteGetString(currentMode, "PRAGMA journal_mode");
|
||||
if (errCode != E_OK) {
|
||||
@ -489,6 +461,10 @@ int SqliteConnection::SetJournalMode(const RdbStoreConfig &config)
|
||||
return errCode;
|
||||
}
|
||||
|
||||
if (config.GetJournalMode().compare(currentMode) == 0) {
|
||||
return E_OK;
|
||||
}
|
||||
|
||||
currentMode = SqliteUtils::StrToUpper(currentMode);
|
||||
if (currentMode != config.GetJournalMode()) {
|
||||
std::string result;
|
||||
@ -505,9 +481,11 @@ int SqliteConnection::SetJournalMode(const RdbStoreConfig &config)
|
||||
}
|
||||
|
||||
if (config.GetJournalMode() == "WAL") {
|
||||
errCode = SetWalSyncMode(config.GetSyncMode());
|
||||
errCode = SetSyncMode(config.GetSyncMode());
|
||||
}
|
||||
if (config.GetJournalMode() == "TRUNCATE") {
|
||||
mode_ = JournalMode::MODE_TRUNCATE;
|
||||
}
|
||||
|
||||
return errCode;
|
||||
}
|
||||
|
||||
@ -563,9 +541,9 @@ int SqliteConnection::SetAutoCheckpoint(const RdbStoreConfig &config)
|
||||
return errCode;
|
||||
}
|
||||
|
||||
int SqliteConnection::SetWalSyncMode(const std::string &syncMode)
|
||||
int SqliteConnection::SetSyncMode(const std::string &syncMode)
|
||||
{
|
||||
std::string targetValue = SqliteGlobalConfig::GetWalSyncMode();
|
||||
std::string targetValue = SqliteGlobalConfig::GetSyncMode();
|
||||
if (syncMode.length() != 0) {
|
||||
targetValue = syncMode;
|
||||
}
|
||||
@ -629,6 +607,7 @@ int SqliteConnection::PrepareAndBind(const std::string &sql, const std::vector<V
|
||||
|
||||
errCode = statement.Prepare(dbHandle, sql);
|
||||
if (errCode != E_OK) {
|
||||
LOG_ERROR("failed to prepare. code %{public}d", errCode);
|
||||
return errCode;
|
||||
}
|
||||
|
||||
@ -1012,5 +991,10 @@ int SqliteConnection::GetMaxVariableNumber()
|
||||
{
|
||||
return maxVariableNumber_;
|
||||
}
|
||||
|
||||
JournalMode SqliteConnection::GetJournalMode()
|
||||
{
|
||||
return mode_;
|
||||
}
|
||||
} // namespace NativeRdb
|
||||
} // namespace OHOS
|
||||
|
@ -32,12 +32,16 @@
|
||||
namespace OHOS {
|
||||
namespace NativeRdb {
|
||||
using namespace OHOS::Rdb;
|
||||
using ConnPool = SqliteConnectionPool;
|
||||
using Conn = SqliteConnection;
|
||||
using SharedConn = std::shared_ptr<SqliteConnection>;
|
||||
using SharedConns = std::vector<SharedConn>;
|
||||
|
||||
constexpr int32_t TRANSACTION_TIMEOUT(2);
|
||||
|
||||
std::shared_ptr<SqliteConnectionPool> SqliteConnectionPool::Create(const RdbStoreConfig &storeConfig, int &errCode)
|
||||
std::shared_ptr<ConnPool> ConnPool::Create(const RdbStoreConfig &storeConfig, int &errCode)
|
||||
{
|
||||
std::shared_ptr<SqliteConnectionPool> pool(new (std::nothrow) SqliteConnectionPool(storeConfig));
|
||||
std::shared_ptr<ConnPool> pool(new (std::nothrow) ConnPool(storeConfig));
|
||||
if (pool == nullptr) {
|
||||
LOG_ERROR("SqliteConnectionPool::Create new failed, pool is nullptr");
|
||||
return nullptr;
|
||||
@ -49,18 +53,18 @@ std::shared_ptr<SqliteConnectionPool> SqliteConnectionPool::Create(const RdbStor
|
||||
return pool;
|
||||
}
|
||||
|
||||
SqliteConnectionPool::SqliteConnectionPool(const RdbStoreConfig& storeConfig)
|
||||
ConnPool::SqliteConnectionPool(const RdbStoreConfig &storeConfig)
|
||||
: config_(storeConfig), writers_(), readers_(), transactionStack_(), transactionUsed_(false)
|
||||
{
|
||||
}
|
||||
|
||||
int SqliteConnectionPool::Init()
|
||||
int ConnPool::Init()
|
||||
{
|
||||
if (config_.GetRoleType() == OWNER) {
|
||||
// write connect count is 1
|
||||
auto errCode = writers_.Initialize(1, config_.GetWriteTime(), [this]() {
|
||||
int32_t errCode = E_OK;
|
||||
auto conn = SqliteConnection::Open(config_, true, errCode);
|
||||
auto conn = Conn::Open(config_, true, errCode);
|
||||
return std::pair{ errCode, conn };
|
||||
});
|
||||
if (errCode != E_OK) {
|
||||
@ -68,43 +72,76 @@ int SqliteConnectionPool::Init()
|
||||
}
|
||||
}
|
||||
|
||||
maxReader_ = GetMaxReaders();
|
||||
maxReader_ = GetMaxReaders(config_);
|
||||
// max read connect count is 64
|
||||
if (maxReader_ > 64) {
|
||||
return E_ARGS_READ_CON_OVERLOAD;
|
||||
}
|
||||
|
||||
return readers_.Initialize(maxReader_, config_.GetReadTime(), [this]() {
|
||||
int32_t errCode = E_OK;
|
||||
auto conn = SqliteConnection::Open(config_, false, errCode);
|
||||
auto conn = Conn::Open(config_, false, errCode);
|
||||
return std::pair{ errCode, conn };
|
||||
});
|
||||
}
|
||||
|
||||
SqliteConnectionPool::~SqliteConnectionPool()
|
||||
ConnPool::~SqliteConnectionPool()
|
||||
{
|
||||
CloseAllConnections();
|
||||
}
|
||||
|
||||
int32_t SqliteConnectionPool::GetMaxReaders()
|
||||
int32_t ConnPool::GetMaxReaders(const RdbStoreConfig &config)
|
||||
{
|
||||
if (config_.GetStorageMode() != StorageMode::MODE_MEMORY && config_.GetJournalMode() == "WAL") {
|
||||
return config_.GetReadConSize();
|
||||
if (config.GetStorageMode() != StorageMode::MODE_MEMORY &&
|
||||
config.GetJournalMode() == GlobalExpr::JOURNAL_MODE_WAL) {
|
||||
return config.GetReadConSize();
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void SqliteConnectionPool::CloseAllConnections()
|
||||
void ConnPool::CloseAllConnections()
|
||||
{
|
||||
writers_.Clear();
|
||||
readers_.Clear();
|
||||
}
|
||||
|
||||
std::shared_ptr<SqliteConnection> SqliteConnectionPool::AcquireConnection(bool isReadOnly)
|
||||
std::shared_ptr<Conn> ConnPool::AcquireConnection(bool isReadOnly)
|
||||
{
|
||||
return Acquire(isReadOnly);
|
||||
}
|
||||
|
||||
std::pair<SharedConn, SharedConns> SqliteConnectionPool::AcquireAll(int32_t time)
|
||||
{
|
||||
using namespace std::chrono;
|
||||
std::pair<SharedConn, SharedConns> result;
|
||||
auto &[writer, readers] = result;
|
||||
auto interval = duration_cast<milliseconds>(seconds(time));
|
||||
auto start = steady_clock::now();
|
||||
writer = Acquire(false, interval);
|
||||
auto usedTime = duration_cast<milliseconds>(steady_clock::now() - start);
|
||||
if (writer == nullptr || usedTime >= interval) {
|
||||
return {};
|
||||
}
|
||||
for (int i = 0; i < maxReader_; ++i) {
|
||||
auto conn = Acquire(true, interval - usedTime);
|
||||
usedTime = duration_cast<milliseconds>(steady_clock::now() - start);
|
||||
if (conn == nullptr || usedTime >= interval) {
|
||||
return {};
|
||||
}
|
||||
auto realConn = AcquireByID(conn->GetId());
|
||||
if (realConn && realConn.use_count() > USE_COUNT_MAX) {
|
||||
return {};
|
||||
}
|
||||
readers.emplace_back(conn);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::shared_ptr<SqliteConnection> SqliteConnectionPool::Acquire(bool isReadOnly, std::chrono::milliseconds ms)
|
||||
{
|
||||
Container *container = (isReadOnly && maxReader_ != 0) ? &readers_ : &writers_;
|
||||
auto node = container->Acquire();
|
||||
auto node = container->Acquire(ms);
|
||||
if (node == nullptr) {
|
||||
const char *header = (isReadOnly && maxReader_ != 0) ? "readers_" : "writers_";
|
||||
container->Dump(header);
|
||||
@ -123,7 +160,7 @@ std::shared_ptr<SqliteConnection> SqliteConnectionPool::AcquireConnection(bool i
|
||||
});
|
||||
}
|
||||
|
||||
std::shared_ptr<SqliteConnection> SqliteConnectionPool::AcquireByID(int32_t id)
|
||||
std::shared_ptr<Conn> ConnPool::AcquireByID(int32_t id)
|
||||
{
|
||||
Container *container = (maxReader_ != 0) ? &readers_ : &writers_;
|
||||
auto node = container->AcquireById(id);
|
||||
@ -139,7 +176,7 @@ std::shared_ptr<SqliteConnection> SqliteConnectionPool::AcquireByID(int32_t id)
|
||||
return conn;
|
||||
}
|
||||
|
||||
void SqliteConnectionPool::ReleaseNode(std::shared_ptr<ConnNode> node)
|
||||
void ConnPool::ReleaseNode(std::shared_ptr<ConnNode> node)
|
||||
{
|
||||
if (node == nullptr) {
|
||||
return;
|
||||
@ -152,7 +189,7 @@ void SqliteConnectionPool::ReleaseNode(std::shared_ptr<ConnNode> node)
|
||||
}
|
||||
}
|
||||
|
||||
int SqliteConnectionPool::AcquireTransaction()
|
||||
int ConnPool::AcquireTransaction()
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(transMutex_);
|
||||
if (transCondition_.wait_for(lock, std::chrono::seconds(TRANSACTION_TIMEOUT), [this] {
|
||||
@ -165,7 +202,7 @@ int SqliteConnectionPool::AcquireTransaction()
|
||||
return E_TRANSACTION_IN_EXECUTE;
|
||||
}
|
||||
|
||||
void SqliteConnectionPool::ReleaseTransaction()
|
||||
void ConnPool::ReleaseTransaction()
|
||||
{
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(transMutex_);
|
||||
@ -174,12 +211,12 @@ void SqliteConnectionPool::ReleaseTransaction()
|
||||
transCondition_.notify_one();
|
||||
}
|
||||
|
||||
int SqliteConnectionPool::RestartReaders()
|
||||
int ConnPool::RestartReaders()
|
||||
{
|
||||
readers_.Clear();
|
||||
return readers_.Initialize(maxReader_, config_.GetReadTime(), [this]() {
|
||||
int32_t errCode = E_OK;
|
||||
auto conn = SqliteConnection::Open(config_, false, errCode);
|
||||
auto conn = Conn::Open(config_, false, errCode);
|
||||
return std::pair{ errCode, conn };
|
||||
});
|
||||
}
|
||||
@ -187,7 +224,7 @@ int SqliteConnectionPool::RestartReaders()
|
||||
/**
|
||||
* The database locale.
|
||||
*/
|
||||
int SqliteConnectionPool::ConfigLocale(const std::string &localeStr)
|
||||
int ConnPool::ConfigLocale(const std::string &localeStr)
|
||||
{
|
||||
auto errCode = readers_.ConfigLocale(localeStr);
|
||||
if (errCode != E_OK) {
|
||||
@ -199,8 +236,8 @@ int SqliteConnectionPool::ConfigLocale(const std::string &localeStr)
|
||||
/**
|
||||
* Rename the backed up database.
|
||||
*/
|
||||
int SqliteConnectionPool::ChangeDbFileForRestore(const std::string &newPath, const std::string &backupPath,
|
||||
const std::vector<uint8_t> &newKey)
|
||||
int ConnPool::ChangeDbFileForRestore(
|
||||
const std::string &newPath, const std::string &backupPath, const std::vector<uint8_t> &newKey)
|
||||
{
|
||||
if (!writers_.IsFull() || !readers_.IsFull()) {
|
||||
LOG_ERROR("Connection pool is busy now!");
|
||||
@ -231,19 +268,52 @@ int SqliteConnectionPool::ChangeDbFileForRestore(const std::string &newPath, con
|
||||
return Init();
|
||||
}
|
||||
|
||||
std::stack<BaseTransaction> &SqliteConnectionPool::GetTransactionStack()
|
||||
std::stack<BaseTransaction> &ConnPool::GetTransactionStack()
|
||||
{
|
||||
return transactionStack_;
|
||||
}
|
||||
|
||||
std::mutex &SqliteConnectionPool::GetTransactionStackMutex()
|
||||
std::mutex &ConnPool::GetTransactionStackMutex()
|
||||
{
|
||||
return transactionStackMutex_;
|
||||
}
|
||||
|
||||
SqliteConnectionPool::ConnNode::ConnNode(std::shared_ptr<SqliteConnection> conn) : connect_(std::move(conn)) {}
|
||||
std::pair<int, std::shared_ptr<Conn>> ConnPool::DisableWalMode()
|
||||
{
|
||||
auto [errCode, node] = writers_.Initialize(1, config_.GetWriteTime(), true, [this]() {
|
||||
int32_t errCode = E_OK;
|
||||
RdbStoreConfig config = config_;
|
||||
config.SetJournalMode(JournalMode::MODE_TRUNCATE);
|
||||
maxReader_ = GetMaxReaders(config);
|
||||
auto conn = Conn::Open(config, true, errCode);
|
||||
return std::pair{ errCode, conn };
|
||||
});
|
||||
if (errCode != E_OK) {
|
||||
return { errCode, nullptr };
|
||||
}
|
||||
auto conn = node->GetConnect();
|
||||
if (conn == nullptr) {
|
||||
return { E_ERROR, nullptr };
|
||||
}
|
||||
auto result =
|
||||
std::shared_ptr<Conn>(conn.get(), [pool = weak_from_this(), hold = node](Conn *) {
|
||||
auto realPool = pool.lock();
|
||||
if (realPool == nullptr) {
|
||||
return;
|
||||
}
|
||||
realPool->ReleaseNode(hold);
|
||||
});
|
||||
return { E_OK, std::move(result) };
|
||||
}
|
||||
|
||||
std::shared_ptr<SqliteConnection> SqliteConnectionPool::ConnNode::GetConnect(bool justHold)
|
||||
int ConnPool::EnableWalMode()
|
||||
{
|
||||
return Init();
|
||||
}
|
||||
|
||||
ConnPool::ConnNode::ConnNode(std::shared_ptr<Conn> conn) : connect_(std::move(conn)) {}
|
||||
|
||||
std::shared_ptr<Conn> ConnPool::ConnNode::GetConnect(bool justHold)
|
||||
{
|
||||
if (!justHold) {
|
||||
tid_ = gettid();
|
||||
@ -252,13 +322,13 @@ std::shared_ptr<SqliteConnection> SqliteConnectionPool::ConnNode::GetConnect(boo
|
||||
return connect_;
|
||||
}
|
||||
|
||||
int64_t SqliteConnectionPool::ConnNode::GetUsingTime() const
|
||||
int64_t ConnPool::ConnNode::GetUsingTime() const
|
||||
{
|
||||
auto time = std::chrono::steady_clock::now() - time_;
|
||||
return std::chrono::duration_cast<std::chrono::milliseconds>(time).count();
|
||||
}
|
||||
|
||||
void SqliteConnectionPool::ConnNode::Unused()
|
||||
void ConnPool::ConnNode::Unused()
|
||||
{
|
||||
tid_ = 0;
|
||||
time_ = std::chrono::steady_clock::now();
|
||||
@ -268,7 +338,7 @@ void SqliteConnectionPool::ConnNode::Unused()
|
||||
}
|
||||
}
|
||||
|
||||
bool SqliteConnectionPool::ConnNode::IsWriter() const
|
||||
bool ConnPool::ConnNode::IsWriter() const
|
||||
{
|
||||
if (connect_ != nullptr) {
|
||||
return connect_->IsWriteConnection();
|
||||
@ -276,7 +346,14 @@ bool SqliteConnectionPool::ConnNode::IsWriter() const
|
||||
return false;
|
||||
}
|
||||
|
||||
int32_t SqliteConnectionPool::Container::Initialize(int32_t max, int32_t timeout, Creator creator)
|
||||
int32_t ConnPool::Container::Initialize(int32_t max, int32_t timeout, Creator creator)
|
||||
{
|
||||
auto [errCode, node] = Initialize(max, timeout, false, std::move(creator));
|
||||
return errCode;
|
||||
}
|
||||
|
||||
std::pair<int32_t, std::shared_ptr<ConnPool::ConnNode>> ConnPool::Container::Initialize(
|
||||
int32_t max, int32_t timeout, bool needAcquire, Creator creator)
|
||||
{
|
||||
std::unique_lock<decltype(mutex_)> lock(mutex_);
|
||||
for (int i = 0; i < max; ++i) {
|
||||
@ -284,7 +361,7 @@ int32_t SqliteConnectionPool::Container::Initialize(int32_t max, int32_t timeout
|
||||
if (conn == nullptr) {
|
||||
nodes_.clear();
|
||||
details_.clear();
|
||||
return error;
|
||||
return { error, nullptr };
|
||||
}
|
||||
auto node = std::make_shared<ConnNode>(conn);
|
||||
node->id_ = right_++;
|
||||
@ -295,10 +372,16 @@ int32_t SqliteConnectionPool::Container::Initialize(int32_t max, int32_t timeout
|
||||
max_ = max;
|
||||
count_ = max;
|
||||
timeout_ = std::chrono::seconds(timeout);
|
||||
return E_OK;
|
||||
std::shared_ptr<ConnNode> connNode = nullptr;
|
||||
if (needAcquire) {
|
||||
connNode = nodes_.back();
|
||||
nodes_.pop_back();
|
||||
count_--;
|
||||
}
|
||||
return { E_OK, connNode };
|
||||
}
|
||||
|
||||
int32_t SqliteConnectionPool::Container::ConfigLocale(const std::string& locale)
|
||||
int32_t ConnPool::Container::ConfigLocale(const std::string& locale)
|
||||
{
|
||||
std::unique_lock<decltype(mutex_)> lock(mutex_);
|
||||
if (max_ != count_) {
|
||||
@ -315,10 +398,11 @@ int32_t SqliteConnectionPool::Container::ConfigLocale(const std::string& locale)
|
||||
return E_OK;
|
||||
}
|
||||
|
||||
std::shared_ptr<SqliteConnectionPool::ConnNode> SqliteConnectionPool::Container::Acquire()
|
||||
std::shared_ptr<ConnPool::ConnNode> ConnPool::Container::Acquire(std::chrono::milliseconds milliS)
|
||||
{
|
||||
auto interval = (milliS == INVALID_TIME) ? timeout_ : milliS;
|
||||
std::unique_lock<decltype(mutex_)> lock(mutex_);
|
||||
if (cond_.wait_for(lock, timeout_, [this] { return count_ > 0; })) {
|
||||
if (cond_.wait_for(lock, interval, [this] { return count_ > 0; })) {
|
||||
auto node = nodes_.back();
|
||||
nodes_.pop_back();
|
||||
count_--;
|
||||
@ -327,7 +411,7 @@ std::shared_ptr<SqliteConnectionPool::ConnNode> SqliteConnectionPool::Container:
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::shared_ptr<SqliteConnectionPool::ConnNode> SqliteConnectionPool::Container::AcquireById(int32_t id)
|
||||
std::shared_ptr<ConnPool::ConnNode> ConnPool::Container::AcquireById(int32_t id)
|
||||
{
|
||||
for (auto& detail : details_) {
|
||||
auto node = detail.lock();
|
||||
@ -341,21 +425,21 @@ std::shared_ptr<SqliteConnectionPool::ConnNode> SqliteConnectionPool::Container:
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int32_t SqliteConnectionPool::Container::Release(std::shared_ptr<ConnNode> node)
|
||||
int32_t ConnPool::Container::Release(std::shared_ptr<ConnNode> node)
|
||||
{
|
||||
{
|
||||
std::unique_lock<decltype(mutex_)> lock(mutex_);
|
||||
if (node->id_ < left_ || node->id_ >= right_) {
|
||||
return E_OK;
|
||||
}
|
||||
nodes_.push_back(node);
|
||||
nodes_.push_front(node);
|
||||
count_++;
|
||||
}
|
||||
cond_.notify_one();
|
||||
return E_OK;
|
||||
}
|
||||
|
||||
int32_t SqliteConnectionPool::Container::Clear()
|
||||
int32_t ConnPool::Container::Clear()
|
||||
{
|
||||
std::list<std::shared_ptr<ConnNode>> nodes;
|
||||
std::list<std::weak_ptr<ConnNode>> details;
|
||||
@ -372,13 +456,13 @@ int32_t SqliteConnectionPool::Container::Clear()
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool SqliteConnectionPool::Container::IsFull()
|
||||
bool ConnPool::Container::IsFull()
|
||||
{
|
||||
std::unique_lock<decltype(mutex_)> lock(mutex_);
|
||||
return max_ == count_;
|
||||
}
|
||||
|
||||
int32_t SqliteConnectionPool::Container::Dump(const char *header)
|
||||
int32_t ConnPool::Container::Dump(const char *header)
|
||||
{
|
||||
std::string info;
|
||||
for (auto& detail : details_) {
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "logger.h"
|
||||
#include "sqlite3sym.h"
|
||||
#include "sqlite_utils.h"
|
||||
#include "rdb_errno.h"
|
||||
|
||||
namespace OHOS {
|
||||
namespace NativeRdb {
|
||||
@ -78,9 +79,9 @@ int SqliteGlobalConfig::GetPageSize()
|
||||
return GlobalExpr::DB_PAGE_SIZE;
|
||||
}
|
||||
|
||||
std::string SqliteGlobalConfig::GetWalSyncMode()
|
||||
std::string SqliteGlobalConfig::GetSyncMode()
|
||||
{
|
||||
return GlobalExpr::WAL_SYNC_MODE;
|
||||
return GlobalExpr::DEFAULE_SYNC_MODE;
|
||||
}
|
||||
|
||||
int SqliteGlobalConfig::GetJournalFileSize()
|
||||
@ -95,7 +96,32 @@ int SqliteGlobalConfig::GetWalAutoCheckpoint()
|
||||
|
||||
std::string SqliteGlobalConfig::GetDefaultJournalMode()
|
||||
{
|
||||
return GlobalExpr::DEFAULT_JOURNAL_MODE;
|
||||
return GlobalExpr::JOURNAL_MODE_WAL;
|
||||
}
|
||||
|
||||
int SqliteGlobalConfig::GetDbPath(const RdbStoreConfig &config, std::string &dbPath)
|
||||
{
|
||||
std::string path;
|
||||
if (config.GetRoleType() == VISITOR) {
|
||||
path = config.GetVisitorDir();
|
||||
} else {
|
||||
path = config.GetPath();
|
||||
}
|
||||
|
||||
if (config.GetStorageMode() == StorageMode::MODE_MEMORY) {
|
||||
if (config.GetRoleType() == VISITOR) {
|
||||
LOG_ERROR("not support MODE_MEMORY, storeName:%{public}s, role:%{public}d", config.GetName().c_str(),
|
||||
config.GetRoleType());
|
||||
return E_NOT_SUPPORT;
|
||||
}
|
||||
dbPath = SqliteGlobalConfig::GetMemoryDbPath();
|
||||
} else if (path.empty() || (path.front() != '/' && path.at(1) != ':')) {
|
||||
LOG_ERROR("SqliteConnection GetDbPath input empty database path");
|
||||
return E_INVALID_FILE_PATH;
|
||||
} else {
|
||||
dbPath = path;
|
||||
}
|
||||
return E_OK;
|
||||
}
|
||||
} // namespace NativeRdb
|
||||
} // namespace OHOS
|
||||
|
@ -85,9 +85,9 @@ constexpr int E_INVALID_COLUMN_INDEX = (E_BASE + 8);
|
||||
constexpr int E_INVALID_COLUMN_TYPE = (E_BASE + 9);
|
||||
|
||||
/**
|
||||
* @brief The error code for a file name is empty.
|
||||
* @brief The error for the database corrupted.
|
||||
*/
|
||||
constexpr int E_EMPTY_FILE_NAME = (E_BASE + 10);
|
||||
constexpr int E_DATA_BASE_CORRUPTED = (E_BASE + 10);
|
||||
|
||||
/**
|
||||
* @brief The error for the current file path is invalid.
|
||||
@ -205,9 +205,9 @@ constexpr int E_EMPTY_NEW_ENCRYPT_KEY = (E_BASE + 32);
|
||||
constexpr int E_CHANGE_UNENCRYPTED_TO_ENCRYPTED = (E_BASE + 33);
|
||||
|
||||
/**
|
||||
* @brief The error code for change encrypt in busy.
|
||||
* @brief The error code for database busy.
|
||||
*/
|
||||
constexpr int E_CHANGE_ENCRYPT_KEY_IN_BUSY = (E_BASE + 34);
|
||||
constexpr int E_DATABASE_BUSY = (E_BASE + 34);
|
||||
|
||||
/**
|
||||
* @brief The error code when the statement not initialized.
|
||||
@ -303,6 +303,11 @@ static constexpr int E_DATABASE_FULL = (E_BASE + 52);
|
||||
* @brief The error when sql is not supported in execute
|
||||
*/
|
||||
static constexpr int E_NOT_SUPPORT_THE_SQL = (E_BASE + 53);
|
||||
|
||||
/**
|
||||
* @brief The database is already attached.
|
||||
*/
|
||||
static constexpr int E_ATTACHED_DATABASE_EXIST = (E_BASE + 54);
|
||||
} // namespace NativeRdb
|
||||
} // namespace OHOS
|
||||
|
||||
|
@ -16,6 +16,7 @@
|
||||
#ifndef NATIVE_RDB_RDB_STORE_H
|
||||
#define NATIVE_RDB_RDB_STORE_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
@ -28,6 +29,7 @@
|
||||
#include "rdb_types.h"
|
||||
#include "rdb_common.h"
|
||||
#include "rdb_errno.h"
|
||||
#include "rdb_store_config.h"
|
||||
|
||||
namespace OHOS::NativeRdb {
|
||||
class API_EXPORT RdbStore {
|
||||
@ -324,11 +326,16 @@ public:
|
||||
* @brief Attaches a database.
|
||||
*
|
||||
* @param alias Indicates the database alias.
|
||||
* @param databasePath Indicates the database file pathname.
|
||||
* @param pathName Indicates the database file pathname.
|
||||
* @param destEncryptKey Indicates the database encrypt key.
|
||||
*/
|
||||
[[deprecated("Use Attach(const RdbStoreConfig &config, const std::string &attachName, int32_t waitTime = 2) "
|
||||
"instead.")]]
|
||||
virtual int Attach(
|
||||
const std::string &alias, const std::string &pathName, const std::vector<uint8_t> destEncryptKey) = 0;
|
||||
const std::string &alias, const std::string &pathName, const std::vector<uint8_t> destEncryptKey)
|
||||
{
|
||||
return E_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the value of the column based on specified conditions.
|
||||
@ -565,6 +572,30 @@ public:
|
||||
* @param table Indicates the specified table.
|
||||
*/
|
||||
virtual int CleanDirtyData(const std::string &table, uint64_t cursor = UINT64_MAX) = 0;
|
||||
|
||||
/**
|
||||
* @brief Attaches a database file to the currently linked database.
|
||||
*
|
||||
* @param config Indicates the {@link RdbStoreConfig} configuration of the database related to this RDB store.
|
||||
* @param attachName Indicates the alias of the database.
|
||||
* @param waitTime Indicates the maximum time allowed for attaching the database file.
|
||||
*/
|
||||
virtual std::pair<int32_t, int32_t> Attach(
|
||||
const RdbStoreConfig &config, const std::string &attachName, int32_t waitTime = 2)
|
||||
{
|
||||
return std::pair<int32_t, int32_t>(0, E_OK);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Detaches a database from this database.
|
||||
*
|
||||
* @param attachName Indicates the alias of the database.
|
||||
* @param waitTime Indicates the maximum time allowed for attaching the database file.
|
||||
*/
|
||||
virtual std::pair<int32_t, int32_t> Detach(const std::string &attachName, int32_t waitTime = 2)
|
||||
{
|
||||
return std::pair<int32_t, int32_t>(0, E_OK);
|
||||
}
|
||||
};
|
||||
} // namespace OHOS::NativeRdb
|
||||
#endif
|
||||
|
@ -186,7 +186,7 @@ public:
|
||||
const std::string &databaseFileType = "", SecurityLevel securityLevel = SecurityLevel::LAST,
|
||||
bool isCreateNecessary = true, bool autoCheck = false, int journalSize = DB_JOURNAL_SIZE,
|
||||
int pageSize = DB_PAGE_SIZE, const std::string &encryptAlgo = DB_DEFAULT_ENCRYPT_ALGO);
|
||||
|
||||
RdbStoreConfig();
|
||||
/**
|
||||
* @brief Destructor.
|
||||
*/
|
||||
|
@ -21,12 +21,13 @@
|
||||
#include <vector>
|
||||
|
||||
#include "abs_rdb_predicates.h"
|
||||
#include "rdb_common.h"
|
||||
#include "rdb_errno.h"
|
||||
#include "rdb_store_config.h"
|
||||
#include "rdb_types.h"
|
||||
#include "result_set.h"
|
||||
#include "value_object.h"
|
||||
#include "values_bucket.h"
|
||||
#include "rdb_common.h"
|
||||
#include "rdb_types.h"
|
||||
|
||||
namespace OHOS::NativeRdb {
|
||||
class RdbStore {
|
||||
public:
|
||||
@ -75,7 +76,10 @@ public:
|
||||
const std::vector<ValueObject> &bindArgs = {}) = 0;
|
||||
virtual int Backup(const std::string databasePath, const std::vector<uint8_t> destEncryptKey = {}) = 0;
|
||||
virtual int Attach(
|
||||
const std::string &alias, const std::string &pathName, const std::vector<uint8_t> destEncryptKey) = 0;
|
||||
const std::string &alias, const std::string &pathName, const std::vector<uint8_t> destEncryptKey)
|
||||
{
|
||||
return E_OK;
|
||||
}
|
||||
|
||||
virtual int Count(int64_t &outValue, const AbsRdbPredicates &predicates) = 0;
|
||||
virtual std::shared_ptr<ResultSet> Query(
|
||||
@ -95,6 +99,9 @@ public:
|
||||
virtual bool IsReadOnly() const = 0;
|
||||
virtual bool IsMemoryRdb() const = 0;
|
||||
virtual int Restore(const std::string backupPath, const std::vector<uint8_t> &newKey = {}) = 0;
|
||||
virtual std::pair<int32_t, int32_t> Attach(
|
||||
const RdbStoreConfig &config, const std::string &attachName, int32_t waitTime = 2) = 0;
|
||||
virtual std::pair<int32_t, int32_t> Detach(const std::string &attachName, int32_t waitTime = 2) = 0;
|
||||
};
|
||||
} // namespace OHOS::NativeRdb
|
||||
#endif
|
||||
|
@ -85,6 +85,7 @@ public:
|
||||
SecurityLevel securityLevel = SecurityLevel::LAST, bool isCreateNecessary = true,
|
||||
bool autoCheck = false, int journalSize = 1048576, int pageSize = 4096,
|
||||
const std::string &encryptAlgo = "sha256");
|
||||
RdbStoreConfig();
|
||||
~RdbStoreConfig();
|
||||
std::string GetName() const;
|
||||
std::string GetPath() const;
|
||||
|
@ -0,0 +1,458 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import {describe, beforeAll, beforeEach, afterEach, afterAll, it, expect} from 'deccjsunit/index'
|
||||
import data_relationalStore from '@ohos.data.relationalStore'
|
||||
import ability_featureAbility from '@ohos.ability.featureAbility'
|
||||
|
||||
|
||||
var context = ability_featureAbility.getContext();
|
||||
|
||||
const TAG = "[RELATIONAL_STORE_JSKITS_TEST]"
|
||||
|
||||
const CREATE_TABLE_TEST = "CREATE TABLE IF NOT EXISTS test (" + "id INTEGER PRIMARY KEY AUTOINCREMENT, " +
|
||||
"name TEXT NOT NULL, " + "age INTEGER, " + "salary REAL, " + "blobType BLOB)";
|
||||
|
||||
const CREATE_TABLE_TEST1 = "CREATE TABLE IF NOT EXISTS test1 (" + "id INTEGER PRIMARY KEY AUTOINCREMENT, " +
|
||||
"name TEXT NOT NULL, " + "age INTEGER, " + "salary REAL, " + "blobType BLOB)";
|
||||
|
||||
|
||||
const STORE_CONFIG = {
|
||||
name: "rdbstore.db",
|
||||
securityLevel: data_relationalStore.SecurityLevel.S1,
|
||||
}
|
||||
|
||||
const STORE_CONFIG1 = {
|
||||
name: "rdbstore1.db",
|
||||
securityLevel: data_relationalStore.SecurityLevel.S1,
|
||||
}
|
||||
|
||||
const STORE_CONFIG2 = {
|
||||
name: "rdbstore2.db",
|
||||
encrypt: true,
|
||||
securityLevel: data_relationalStore.SecurityLevel.S1,
|
||||
}
|
||||
|
||||
const STORE_CONFIG3 = {
|
||||
name: "rdbstore3.db",
|
||||
encrypt: true,
|
||||
securityLevel: data_relationalStore.SecurityLevel.S1,
|
||||
}
|
||||
|
||||
describe('ActsRdbStoreAttachTest', function () {
|
||||
beforeAll(async function () {
|
||||
console.info(TAG + 'beforeAll');
|
||||
})
|
||||
|
||||
beforeEach(async function () {
|
||||
console.info(TAG + 'beforeEach');
|
||||
let attachStore = await data_relationalStore.getRdbStore(context, STORE_CONFIG1);
|
||||
await attachStore.executeSql(CREATE_TABLE_TEST1);
|
||||
let attachStore1 = await data_relationalStore.getRdbStore(context, STORE_CONFIG2);
|
||||
await attachStore1.executeSql(CREATE_TABLE_TEST1);
|
||||
})
|
||||
|
||||
afterEach(async function () {
|
||||
console.info(TAG + 'afterEach')
|
||||
await data_relationalStore.deleteRdbStore(context, "rdbstore.db");
|
||||
await data_relationalStore.deleteRdbStore(context, "rdbstore1.db");
|
||||
await data_relationalStore.deleteRdbStore(context, "rdbstore2.db");
|
||||
await data_relationalStore.deleteRdbStore(context, "rdbstore3.db");
|
||||
})
|
||||
|
||||
afterAll(async function () {
|
||||
console.info(TAG + 'afterAll');
|
||||
})
|
||||
|
||||
|
||||
async function attachInsert(store, tableName) {
|
||||
var u8 = new Uint8Array([1, 2, 3])
|
||||
const valueBucket = {
|
||||
"name": "zhangsan",
|
||||
"age": 18,
|
||||
"salary": 100.5,
|
||||
"blobType": u8,
|
||||
};
|
||||
await store.insert(tableName, valueBucket);
|
||||
}
|
||||
|
||||
async function attachBatchInsert(store, tableName) {
|
||||
var u8 = new Uint8Array([1, 2, 3])
|
||||
const valueBucket = {
|
||||
"name": "zhangsan",
|
||||
"age": 18,
|
||||
"salary": 100.5,
|
||||
"blobType": u8,
|
||||
};
|
||||
let valueBucketArray = new Array();
|
||||
for (let i = 0; i < 10; i++) {
|
||||
valueBucketArray.push(valueBucket);
|
||||
}
|
||||
await store.batchInsert(tableName, valueBucketArray);
|
||||
}
|
||||
|
||||
async function insertCheck(store, tableName, ret) {
|
||||
let predicates = new data_relationalStore.RdbPredicates(tableName);
|
||||
let resultSet = await store.query(predicates);
|
||||
let count = resultSet.rowCount;
|
||||
expect(ret).assertEqual(count);
|
||||
resultSet.close();
|
||||
}
|
||||
|
||||
async function updateCheck(store, tableName) {
|
||||
var u8 = new Uint8Array([4, 5, 6]);
|
||||
const valueBucket = {
|
||||
"name": "lisi",
|
||||
"age": 20,
|
||||
"salary": 200.5,
|
||||
"blobType": u8,
|
||||
};
|
||||
let predicates = new data_relationalStore.RdbPredicates(tableName)
|
||||
predicates.equalTo("id", "1");
|
||||
let ret = await store.update(valueBucket, predicates);
|
||||
expect(1).assertEqual(ret);
|
||||
}
|
||||
|
||||
async function deleteCheck(store, tableName, count) {
|
||||
let predicates = new data_relationalStore.RdbPredicates(tableName);
|
||||
let ret = await store.delete(predicates);
|
||||
expect(count).assertEqual(ret);
|
||||
}
|
||||
|
||||
async function attachCheck(store) {
|
||||
await attachInsert(store, "test");
|
||||
await insertCheck(store, "test", 2);
|
||||
await updateCheck(store, "test");
|
||||
await attachBatchInsert(store, "test");
|
||||
await insertCheck(store, "test", 12);
|
||||
await deleteCheck(store, "test", 12);
|
||||
|
||||
await attachInsert(store, "test1");
|
||||
await insertCheck(store, "test1", 1)
|
||||
await updateCheck(store, "test1");
|
||||
await attachBatchInsert(store, "test1");
|
||||
await insertCheck(store, "test1", 11);
|
||||
await deleteCheck(store, "test1", 11);
|
||||
}
|
||||
|
||||
console.log(TAG + "*************Unit Test Begin*************");
|
||||
|
||||
/**
|
||||
* @tc.name the attach function
|
||||
* @tc.number SUB_DDM_AppDataFWK_JSRDB_RdbStore_attach_001
|
||||
* @tc.desc non encrypted database attach non encrypted database
|
||||
*/
|
||||
it('testRdbStoreAttach0001', 0, async function () {
|
||||
console.log(TAG + "************* testRdbStoreAttach0001 start *************");
|
||||
let store = await data_relationalStore.getRdbStore(context, STORE_CONFIG);
|
||||
await store.executeSql(CREATE_TABLE_TEST);
|
||||
await attachInsert(store, "test");
|
||||
|
||||
let number = await store.attach(context, STORE_CONFIG1, "attachDB");
|
||||
expect(1).assertEqual(number);
|
||||
|
||||
await attachCheck(store);
|
||||
expect(0).assertEqual(await store.detach("attachDB"))
|
||||
console.log(TAG + "************* testRdbStoreAttach0001 end *************");
|
||||
})
|
||||
|
||||
/**
|
||||
* @tc.name the attach function
|
||||
* @tc.number SUB_DDM_AppDataFWK_JSRDB_RdbStore_attach_002
|
||||
* @tc.desc non encrypted database attach encrypted database
|
||||
*/
|
||||
it('testRdbStoreAttach0002', 0, async function () {
|
||||
console.log(TAG + "************* testRdbStoreAttach0002 start *************");
|
||||
let store = await data_relationalStore.getRdbStore(context, STORE_CONFIG);
|
||||
await store.executeSql(CREATE_TABLE_TEST);
|
||||
await attachInsert(store, "test");
|
||||
|
||||
let number = await store.attach(context, STORE_CONFIG2, "attachDB");
|
||||
expect(1).assertEqual(number);
|
||||
|
||||
await attachCheck(store);
|
||||
expect(0).assertEqual(await store.detach("attachDB"))
|
||||
console.log(TAG + "************* testRdbStoreAttach0002 end *************");
|
||||
})
|
||||
|
||||
/**
|
||||
* @tc.name the attach function
|
||||
* @tc.number SUB_DDM_AppDataFWK_JSRDB_RdbStore_attach_003
|
||||
* @tc.desc encrypted database attach encrypted database
|
||||
*/
|
||||
it('testRdbStoreAttach0003', 0, async function () {
|
||||
console.log(TAG + "************* testRdbStoreAttach0003 start *************");
|
||||
let store = await data_relationalStore.getRdbStore(context, STORE_CONFIG3);
|
||||
await store.executeSql(CREATE_TABLE_TEST);
|
||||
await attachInsert(store, "test");
|
||||
|
||||
let number = await store.attach(context, STORE_CONFIG2, "attachDB");
|
||||
expect(1).assertEqual(number);
|
||||
|
||||
await attachCheck(store);
|
||||
expect(0).assertEqual(await store.detach("attachDB"));
|
||||
console.log(TAG + "************* testRdbStoreAttach0003 end *************");
|
||||
})
|
||||
|
||||
/**
|
||||
* @tc.name the attach function
|
||||
* @tc.number SUB_DDM_AppDataFWK_JSRDB_RdbStore_attach_004
|
||||
* @tc.desc encrypted databases are not supported for attaching non encrypted databases
|
||||
*/
|
||||
it('testRdbStoreAttach0004', 0, async function () {
|
||||
console.log(TAG + "************* testRdbStoreAttach0004 start *************");
|
||||
let store = await data_relationalStore.getRdbStore(context, STORE_CONFIG3);
|
||||
try {
|
||||
await store.attach(context, STORE_CONFIG1, "attachDB");
|
||||
expect().assertFail();
|
||||
} catch(e) {
|
||||
console.log("attach err: failed, err: code=" + e.code + " message=" + e.message)
|
||||
expect(801).assertEqual(e.code);
|
||||
}
|
||||
console.log(TAG + "************* testRdbStoreAttach0004 end *************");
|
||||
})
|
||||
|
||||
/**
|
||||
* @tc.name the attach function
|
||||
* @tc.number SUB_DDM_AppDataFWK_JSRDB_RdbStore_attach_005
|
||||
* @tc.desc non encrypted database attach non encrypted database
|
||||
*/
|
||||
it('testRdbStoreAttach0005', 0, async function () {
|
||||
console.log(TAG + "************* testRdbStoreAttach0005 start *************");
|
||||
let store = await data_relationalStore.getRdbStore(context, STORE_CONFIG);
|
||||
await store.executeSql(CREATE_TABLE_TEST);
|
||||
await attachInsert(store, "test");
|
||||
let number = await store.attach("/data/storage/el2/database/entry/rdb/rdbstore1.db", "attachDB");
|
||||
expect(1).assertEqual(number);
|
||||
await attachCheck(store);
|
||||
expect(0).assertEqual(await store.detach("attachDB"));
|
||||
console.log(TAG + "************* testRdbStoreAttach0005 end *************");
|
||||
})
|
||||
|
||||
/**
|
||||
* @tc.name the attach function
|
||||
* @tc.number SUB_DDM_AppDataFWK_JSRDB_RdbStore_attach_006
|
||||
* @tc.desc path error for non encrypted database
|
||||
*/
|
||||
it('testRdbStoreAttach0006', 0, async function () {
|
||||
console.log(TAG + "************* testRdbStoreAttach0006 start *************");
|
||||
let store = await data_relationalStore.getRdbStore(context, STORE_CONFIG);
|
||||
await store.executeSql(CREATE_TABLE_TEST);
|
||||
await attachInsert(store, "test");
|
||||
|
||||
let STORE_CONFIG4 = {
|
||||
name: "/wrong/rdbstore.db",
|
||||
securityLevel: data_relationalStore.SecurityLevel.S1,
|
||||
}
|
||||
try {
|
||||
await store.attach(context, STORE_CONFIG4, "attachDB");
|
||||
} catch (e) {
|
||||
console.log("catch err: failed, err: code=" + e.code + " message=" + e.message)
|
||||
expect("401").assertEqual(e.code);
|
||||
}
|
||||
console.log(TAG + "************* testRdbStoreAttach0006 end *************");
|
||||
})
|
||||
|
||||
/**
|
||||
* @tc.name the attach function
|
||||
* @tc.number SUB_DDM_AppDataFWK_JSRDB_RdbStore_attach_007
|
||||
* @tc.desc non encrypted database attach non encrypted database with same table name
|
||||
*/
|
||||
it('testRdbStoreAttach0007', 0, async function () {
|
||||
console.log(TAG + "************* testRdbStoreAttach0007 start *************");
|
||||
let store = await data_relationalStore.getRdbStore(context, STORE_CONFIG);
|
||||
await store.executeSql(CREATE_TABLE_TEST1);
|
||||
await attachInsert(store, "test1");
|
||||
|
||||
let number = await store.attach(context, STORE_CONFIG1, "attachDB");
|
||||
expect(1).assertEqual(number);
|
||||
|
||||
await attachInsert(store, "test1");
|
||||
await insertCheck(store, "test1", 2);
|
||||
await updateCheck(store, "test1");
|
||||
await attachBatchInsert(store, "test1");
|
||||
await insertCheck(store, "test1", 12);
|
||||
await deleteCheck(store, "test1", 12);
|
||||
|
||||
await attachInsert(store, "attachDB.test1");
|
||||
await insertCheck(store, "attachDB.test1", 1)
|
||||
await updateCheck(store, "attachDB.test1");
|
||||
await attachBatchInsert(store, "attachDB.test1");
|
||||
await insertCheck(store, "attachDB.test1", 11);
|
||||
await deleteCheck(store, "attachDB.test1", 11);
|
||||
|
||||
expect(0).assertEqual(await store.detach("attachDB"))
|
||||
console.log(TAG + "************* testRdbStoreAttach0007 end *************");
|
||||
})
|
||||
|
||||
/**
|
||||
* @tc.name the attach function
|
||||
* @tc.number SUB_DDM_AppDataFWK_JSRDB_RdbStore_attach_008
|
||||
* @tc.desc resultSet occupies connection, attach failed
|
||||
*/
|
||||
it('testRdbStoreAttach0008', 0, async function () {
|
||||
console.log(TAG + "************* testRdbStoreAttach0008 start *************");
|
||||
let store = await data_relationalStore.getRdbStore(context, STORE_CONFIG);
|
||||
await store.executeSql(CREATE_TABLE_TEST);
|
||||
await attachBatchInsert(store, "test");
|
||||
|
||||
let predicates = new data_relationalStore.RdbPredicates("test");
|
||||
let resultSet = await store.query(predicates);
|
||||
let count = resultSet.rowCount;
|
||||
expect(10).assertEqual(count);
|
||||
try {
|
||||
await store.attach("/data/storage/el2/database/entry/rdb/rdbstore1.db", "attachDB");
|
||||
expect().assertFail();
|
||||
} catch(e) {
|
||||
expect(14800015).assertEqual(e.code);
|
||||
}
|
||||
resultSet.close();
|
||||
console.log(TAG + "************* testRdbStoreAttach0008 end *************");
|
||||
})
|
||||
|
||||
/**
|
||||
* @tc.name the attach function
|
||||
* @tc.number SUB_DDM_AppDataFWK_JSRDB_RdbStore_attach_009
|
||||
* @tc.desc repeat attach using the same alias
|
||||
*/
|
||||
it('testRdbStoreAttach0009', 0, async function () {
|
||||
console.log(TAG + "************* testRdbStoreAttach0009 start *************");
|
||||
let store = await data_relationalStore.getRdbStore(context, STORE_CONFIG);
|
||||
await store.executeSql(CREATE_TABLE_TEST);
|
||||
await attachBatchInsert(store, "test");
|
||||
let number = await store.attach(context, STORE_CONFIG1, 'attachDB');
|
||||
expect(1).assertEqual(number);
|
||||
try {
|
||||
await store.attach(context, STORE_CONFIG1, 'attachDB');
|
||||
expect().assertFail();
|
||||
} catch(e) {
|
||||
console.log("testRdbStoreAttach0009: failed, err: code=" + e.code + " message=" + e.message);
|
||||
expect(14800016).assertEqual(e.code);
|
||||
}
|
||||
expect(0).assertEqual(await store.detach("attachDB"));
|
||||
|
||||
console.log(TAG + "************* testRdbStoreAttach0009 end *************");
|
||||
})
|
||||
|
||||
/**
|
||||
* @tc.name the attach function
|
||||
* @tc.number SUB_DDM_AppDataFWK_JSRDB_RdbStore_attach_0010
|
||||
* @tc.desc WaitTime exceeds maximum limit
|
||||
*/
|
||||
it('testRdbStoreAttach00010', 0, async function () {
|
||||
console.log(TAG + "************* testRdbStoreAttach00010 start *************");
|
||||
let store = await data_relationalStore.getRdbStore(context, STORE_CONFIG);
|
||||
await store.executeSql(CREATE_TABLE_TEST);
|
||||
await attachBatchInsert(store, "test");
|
||||
let number = await store.attach(context, STORE_CONFIG1, 'attachDB', 300);
|
||||
expect(1).assertEqual(number);
|
||||
try {
|
||||
await store.attach(context, STORE_CONFIG1, 'attachDB', 301);
|
||||
expect().assertFail();
|
||||
} catch(e) {
|
||||
console.log("testRdbStoreAttach00010: failed, err: code=" + e.code + " message=" + e.message);
|
||||
expect("401").assertEqual(e.code);
|
||||
}
|
||||
expect(0).assertEqual(await store.detach("attachDB"));
|
||||
|
||||
console.log(TAG + "************* testRdbStoreAttach00010 end *************");
|
||||
})
|
||||
|
||||
/**
|
||||
* @tc.name the attach function
|
||||
* @tc.number SUB_DDM_AppDataFWK_JSRDB_RdbStore_attach_0011
|
||||
* @tc.desc WaitTime exceeds the minimum limit
|
||||
*/
|
||||
it('testRdbStoreAttach00011', 0, async function () {
|
||||
console.log(TAG + "************* testRdbStoreAttach00011 start *************");
|
||||
let store = await data_relationalStore.getRdbStore(context, STORE_CONFIG);
|
||||
await store.executeSql(CREATE_TABLE_TEST);
|
||||
await attachBatchInsert(store, "test");
|
||||
let number = await store.attach(context, STORE_CONFIG1, 'attachDB', 1);
|
||||
expect(1).assertEqual(number);
|
||||
try {
|
||||
await store.attach(context, STORE_CONFIG1, 'attachDB', -1);
|
||||
expect().assertFail();
|
||||
} catch(e) {
|
||||
console.log("testRdbStoreAttach00011: failed, err: code=" + e.code + " message=" + e.message);
|
||||
expect('401').assertEqual(e.code);
|
||||
}
|
||||
expect(0).assertEqual(await store.detach("attachDB"));
|
||||
|
||||
console.log(TAG + "************* testRdbStoreAttach00011 end *************");
|
||||
})
|
||||
|
||||
/**
|
||||
* @tc.name the attach function
|
||||
* @tc.number SUB_DDM_AppDataFWK_JSRDB_RdbStore_attach_0012
|
||||
* @tc.desc the alias cannot be empty
|
||||
*/
|
||||
it('testRdbStoreAttach00012', 0, async function () {
|
||||
console.log(TAG + "************* testRdbStoreAttach00012 start *************");
|
||||
let store = await data_relationalStore.getRdbStore(context, STORE_CONFIG);
|
||||
await store.executeSql(CREATE_TABLE_TEST);
|
||||
await attachBatchInsert(store, "test");
|
||||
try {
|
||||
await store.attach(context, STORE_CONFIG1, '');
|
||||
expect().assertFail();
|
||||
} catch(e) {
|
||||
console.log("testRdbStoreAttach00012 : failed, err: code=" + e.code + " message=" + e.message);
|
||||
expect('401').assertEqual(e.code);
|
||||
}
|
||||
console.log(TAG + "************* testRdbStoreAttach00012 end *************");
|
||||
})
|
||||
|
||||
/**
|
||||
* @tc.name the attach function
|
||||
* @tc.number SUB_DDM_AppDataFWK_JSRDB_RdbStore_attach_0013
|
||||
* @tc.desc input error path
|
||||
*/
|
||||
it('testRdbStoreAttach00013', 0, async function () {
|
||||
console.log(TAG + "************* testRdbStoreAttach00013 start *************");
|
||||
let store = await data_relationalStore.getRdbStore(context, STORE_CONFIG);
|
||||
await store.executeSql(CREATE_TABLE_TEST);
|
||||
await attachBatchInsert(store, "test");
|
||||
try {
|
||||
await store.attach("/path/errPath/attach.db", "attachDB");
|
||||
expect().assertFail();
|
||||
} catch(e) {
|
||||
console.log("testRdbStoreAttach00013 : failed, err: code=" + e.code + " message=" + e.message);
|
||||
expect(14800010).assertEqual(e.code);
|
||||
}
|
||||
console.log(TAG + "************* testRdbStoreAttach00013 end *************");
|
||||
})
|
||||
|
||||
/**
|
||||
* @tc.name the attach function
|
||||
* @tc.number SUB_DDM_AppDataFWK_JSRDB_RdbStore_attach_0014
|
||||
* @tc.desc input empty path
|
||||
*/
|
||||
it('testRdbStoreAttach00014', 0, async function () {
|
||||
console.log(TAG + "************* testRdbStoreAttach00014 start *************");
|
||||
let store = await data_relationalStore.getRdbStore(context, STORE_CONFIG);
|
||||
await store.executeSql(CREATE_TABLE_TEST);
|
||||
await attachBatchInsert(store, "test");
|
||||
try {
|
||||
await store.attach("", "attachDB");
|
||||
expect().assertFail();
|
||||
} catch(e) {
|
||||
console.log("testRdbStoreAttach00014 : failed, err: code=" + e.code + " message=" + e.message);
|
||||
expect('401').assertEqual(e.code);
|
||||
}
|
||||
console.log(TAG + "************* testRdbStoreAttach00014 end *************");
|
||||
})
|
||||
|
||||
console.log(TAG + "*************Unit Test End*************");
|
||||
})
|
@ -33,13 +33,16 @@ public:
|
||||
void TearDown();
|
||||
void QueryCheck1(std::shared_ptr<RdbStore> &store) const;
|
||||
void QueryCheck2(std::shared_ptr<RdbStore> &store) const;
|
||||
void DeleteCheck(std::shared_ptr<RdbStore> &store) const;
|
||||
void UpdateCheck(std::shared_ptr<RdbStore> &store) const;
|
||||
void InsertCheck(std::shared_ptr<RdbStore> &store) const;
|
||||
|
||||
static const std::string MAIN_DATABASE_NAME;
|
||||
static const std::string ATTACHED_DATABASE_NAME;
|
||||
static constexpr const char *MAIN_DATABASE_NAME = "/data/test/main.db";
|
||||
static constexpr const char *ATTACHED_DATABASE_NAME = "/data/test/attached.db";
|
||||
static constexpr const char *ENCRYPT_ATTACHED_DATABASE_NAME = "/data/test/encrypt_attached.db";
|
||||
static constexpr int BUSY_TIMEOUT = 2;
|
||||
};
|
||||
|
||||
const std::string RdbAttachTest::MAIN_DATABASE_NAME = RDB_TEST_PATH + "main.db";
|
||||
|
||||
class MainOpenCallback : public RdbOpenCallback {
|
||||
public:
|
||||
int OnCreate(RdbStore &store) override;
|
||||
@ -60,8 +63,6 @@ int MainOpenCallback::OnUpgrade(RdbStore &store, int oldVersion, int newVersion)
|
||||
return E_OK;
|
||||
}
|
||||
|
||||
const std::string RdbAttachTest::ATTACHED_DATABASE_NAME = RDB_TEST_PATH + "attached.db";
|
||||
|
||||
class AttachedOpenCallback : public RdbOpenCallback {
|
||||
public:
|
||||
int OnCreate(RdbStore &store) override;
|
||||
@ -119,7 +120,7 @@ HWTEST_F(RdbAttachTest, RdbStore_Attach_001, TestSize.Level1)
|
||||
std::shared_ptr<RdbStore> store = RdbHelper::GetRdbStore(config, 1, helper, errCode);
|
||||
EXPECT_NE(store, nullptr);
|
||||
|
||||
int ret = store->ExecuteSql("ATTACH '" + ATTACHED_DATABASE_NAME + "' as attached");
|
||||
int ret = store->ExecuteSql("ATTACH '" + std::string(ATTACHED_DATABASE_NAME) + "' as attached");
|
||||
EXPECT_EQ(ret, E_NOT_SUPPORTED_ATTACH_IN_WAL_MODE);
|
||||
}
|
||||
|
||||
@ -137,23 +138,10 @@ HWTEST_F(RdbAttachTest, RdbStore_Attach_002, TestSize.Level1)
|
||||
std::shared_ptr<RdbStore> store = RdbHelper::GetRdbStore(config, 1, helper, errCode);
|
||||
EXPECT_NE(store, nullptr);
|
||||
|
||||
int ret = store->ExecuteSql("ATTACH DATABASE '" + ATTACHED_DATABASE_NAME + "' as 'attached'");
|
||||
int ret = store->ExecuteSql("ATTACH DATABASE '" + std::string(ATTACHED_DATABASE_NAME) + "' as 'attached'");
|
||||
EXPECT_EQ(ret, E_OK);
|
||||
|
||||
int64_t id;
|
||||
ValuesBucket values;
|
||||
values.PutInt("id", 1);
|
||||
values.PutString("name", std::string("zhangsan"));
|
||||
ret = store->Insert(id, "test1", values);
|
||||
EXPECT_EQ(ret, E_OK);
|
||||
EXPECT_EQ(id, 1);
|
||||
|
||||
values.Clear();
|
||||
values.PutInt("id", 1);
|
||||
values.PutString("name", std::string("lisi"));
|
||||
ret = store->Insert(id, "test2", values);
|
||||
EXPECT_EQ(ret, E_OK);
|
||||
EXPECT_EQ(id, 1);
|
||||
InsertCheck(store);
|
||||
|
||||
QueryCheck1(store);
|
||||
|
||||
@ -162,23 +150,21 @@ HWTEST_F(RdbAttachTest, RdbStore_Attach_002, TestSize.Level1)
|
||||
|
||||
QueryCheck2(store);
|
||||
|
||||
ret = store->ExecuteSql("attach database '" + ATTACHED_DATABASE_NAME + "' as 'attached'");
|
||||
ret = store->ExecuteSql("attach database '" + std::string(ATTACHED_DATABASE_NAME) + "' as 'attached'");
|
||||
EXPECT_EQ(ret, E_OK);
|
||||
|
||||
ret = store->ExecuteSql("detach database 'attached'");
|
||||
EXPECT_EQ(ret, E_OK);
|
||||
}
|
||||
|
||||
|
||||
/* *
|
||||
/**
|
||||
* @tc.name: RdbStore_Attach_003
|
||||
* @tc.desc: Abnormal testCase for Attach
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(RdbAttachTest, RdbStore_Attach_003, TestSize.Level2)
|
||||
{
|
||||
const std::string alias = "attached";
|
||||
std::vector<uint8_t> destEncryptKey;
|
||||
const std::string attachedName = "attached";
|
||||
RdbStoreConfig config(RdbAttachTest::MAIN_DATABASE_NAME);
|
||||
MainOpenCallback helper;
|
||||
int errCode = E_OK;
|
||||
@ -187,33 +173,113 @@ HWTEST_F(RdbAttachTest, RdbStore_Attach_003, TestSize.Level2)
|
||||
std::shared_ptr<RdbStore> store1 = RdbHelper::GetRdbStore(config, 1, helper, errCode);
|
||||
EXPECT_NE(nullptr, store1);
|
||||
EXPECT_EQ(E_OK, errCode);
|
||||
RdbStoreConfig attachedConfig(RdbAttachTest::ATTACHED_DATABASE_NAME);
|
||||
auto ret = store1->Attach(attachedConfig, attachedName, BUSY_TIMEOUT);
|
||||
EXPECT_EQ(E_OK, ret.first);
|
||||
EXPECT_EQ(1, ret.second);
|
||||
QueryCheck1(store1);
|
||||
// use the same attachedName to attach again
|
||||
ret = store1->Attach(attachedConfig, attachedName, BUSY_TIMEOUT);
|
||||
EXPECT_EQ(E_ATTACHED_DATABASE_EXIST, ret.first);
|
||||
|
||||
int ret = store1->Attach(alias, RdbAttachTest::ATTACHED_DATABASE_NAME, destEncryptKey);
|
||||
EXPECT_EQ(E_NOT_SUPPORTED_ATTACH_IN_WAL_MODE, ret);
|
||||
RdbHelper::DeleteRdbStore(RdbAttachTest::MAIN_DATABASE_NAME);
|
||||
ret = store1->Detach(attachedName);
|
||||
EXPECT_EQ(E_OK, ret.first);
|
||||
EXPECT_EQ(0, ret.second);
|
||||
QueryCheck2(store1);
|
||||
}
|
||||
|
||||
// journal mode is TRUNCATE
|
||||
// destEncryptKey is empty and isEncrypt_ is false
|
||||
config.SetJournalMode(JournalMode::MODE_TRUNCATE);
|
||||
std::shared_ptr<RdbStore> store2 = RdbHelper::GetRdbStore(config, 1, helper, errCode);
|
||||
EXPECT_NE(nullptr, store2);
|
||||
/**
|
||||
* @tc.name: RdbStore_Attach_004
|
||||
* @tc.desc: Abnormal testCase for Attach with wrong path
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(RdbAttachTest, RdbStore_Attach_004, TestSize.Level2)
|
||||
{
|
||||
const std::string attachedName = "attached";
|
||||
RdbStoreConfig config(RdbAttachTest::MAIN_DATABASE_NAME);
|
||||
MainOpenCallback helper;
|
||||
int errCode = E_OK;
|
||||
|
||||
// journal mode is wal
|
||||
std::shared_ptr<RdbStore> store1 = RdbHelper::GetRdbStore(config, 1, helper, errCode);
|
||||
EXPECT_NE(nullptr, store1);
|
||||
EXPECT_EQ(E_OK, errCode);
|
||||
ret = store2->Attach(alias, RdbAttachTest::ATTACHED_DATABASE_NAME, destEncryptKey);
|
||||
EXPECT_EQ(E_OK, ret);
|
||||
RdbStoreConfig attachedConfig("/wrong/path");
|
||||
auto ret = store1->Attach(attachedConfig, attachedName, BUSY_TIMEOUT);
|
||||
EXPECT_EQ(E_INVALID_FILE_PATH, ret.first);
|
||||
}
|
||||
|
||||
// destEncryptKey is not empty and isEncrypt_ is false
|
||||
destEncryptKey = {1};
|
||||
ret = store2->Attach(alias, RdbAttachTest::ATTACHED_DATABASE_NAME, destEncryptKey);
|
||||
EXPECT_NE(E_OK, ret);
|
||||
RdbHelper::DeleteRdbStore(RdbAttachTest::MAIN_DATABASE_NAME);
|
||||
/**
|
||||
* @tc.name: RdbStore_Attach_005
|
||||
* @tc.desc: Abnormal testCase for Attach encrypted database
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(RdbAttachTest, RdbStore_Attach_005, TestSize.Level2)
|
||||
{
|
||||
int errCode = E_OK;
|
||||
AttachedOpenCallback attachedHelper;
|
||||
RdbStoreConfig encryptAttachedConfig(RdbAttachTest::ENCRYPT_ATTACHED_DATABASE_NAME);
|
||||
encryptAttachedConfig.SetEncryptStatus(true);
|
||||
std::shared_ptr<RdbStore> encryptAttachedStore =
|
||||
RdbHelper::GetRdbStore(encryptAttachedConfig, 1, attachedHelper, errCode);
|
||||
EXPECT_NE(encryptAttachedStore, nullptr);
|
||||
|
||||
// destEncryptKey is not empty and isEncrypt_ is true
|
||||
config.SetEncryptStatus(true);
|
||||
std::shared_ptr<RdbStore> store3 = RdbHelper::GetRdbStore(config, 1, helper, errCode);
|
||||
EXPECT_NE(nullptr, store3);
|
||||
encryptAttachedStore = nullptr;
|
||||
const std::string attachedName = "attached";
|
||||
RdbStoreConfig config(RdbAttachTest::MAIN_DATABASE_NAME);
|
||||
MainOpenCallback helper;
|
||||
|
||||
// journal mode is wal
|
||||
std::shared_ptr<RdbStore> store1 = RdbHelper::GetRdbStore(config, 1, helper, errCode);
|
||||
EXPECT_NE(nullptr, store1);
|
||||
EXPECT_EQ(E_OK, errCode);
|
||||
ret = store3->Attach(alias, RdbAttachTest::ATTACHED_DATABASE_NAME, destEncryptKey);
|
||||
EXPECT_NE(E_OK, ret);
|
||||
auto ret = store1->Attach(encryptAttachedConfig, attachedName, BUSY_TIMEOUT);
|
||||
EXPECT_EQ(E_OK, ret.first);
|
||||
EXPECT_EQ(1, ret.second);
|
||||
|
||||
int64_t id;
|
||||
ValuesBucket values;
|
||||
values.PutInt("id", 1);
|
||||
values.PutString("name", std::string("lisi"));
|
||||
int res = store1->Insert(id, "test2", values);
|
||||
EXPECT_EQ(res, E_OK);
|
||||
EXPECT_EQ(id, 1);
|
||||
QueryCheck1(store1);
|
||||
|
||||
ret = store1->Detach(attachedName);
|
||||
EXPECT_EQ(E_OK, ret.first);
|
||||
EXPECT_EQ(0, ret.second);
|
||||
QueryCheck2(store1);
|
||||
RdbHelper::DeleteRdbStore(RdbAttachTest::ENCRYPT_ATTACHED_DATABASE_NAME);
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: RdbStore_Attach_006
|
||||
* @tc.desc: Abnormal testCase for Attach
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(RdbAttachTest, RdbStore_Attach_006, TestSize.Level2)
|
||||
{
|
||||
const std::string attachedName = "attached";
|
||||
RdbStoreConfig config(RdbAttachTest::MAIN_DATABASE_NAME);
|
||||
MainOpenCallback helper;
|
||||
int errCode = E_OK;
|
||||
|
||||
// journal mode is wal
|
||||
std::shared_ptr<RdbStore> store1 = RdbHelper::GetRdbStore(config, 1, helper, errCode);
|
||||
EXPECT_NE(nullptr, store1);
|
||||
EXPECT_EQ(E_OK, errCode);
|
||||
RdbStoreConfig attachedConfig(RdbAttachTest::ATTACHED_DATABASE_NAME);
|
||||
auto ret = store1->Attach(attachedConfig, attachedName, BUSY_TIMEOUT);
|
||||
EXPECT_EQ(E_OK, ret.first);
|
||||
EXPECT_EQ(1, ret.second);
|
||||
|
||||
UpdateCheck(store1);
|
||||
DeleteCheck(store1);
|
||||
|
||||
ret = store1->Detach(attachedName);
|
||||
EXPECT_EQ(E_OK, ret.first);
|
||||
EXPECT_EQ(0, ret.second);
|
||||
}
|
||||
|
||||
void RdbAttachTest::QueryCheck1(std::shared_ptr<RdbStore> &store) const
|
||||
@ -275,4 +341,88 @@ void RdbAttachTest::QueryCheck2(std::shared_ptr<RdbStore> &store) const
|
||||
// detached, no table test2
|
||||
resultSet = store->QuerySql("SELECT * FROM test2");
|
||||
EXPECT_NE(resultSet, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
void RdbAttachTest::DeleteCheck(std::shared_ptr<RdbStore> &store) const
|
||||
{
|
||||
int changedRows = 0;
|
||||
AbsRdbPredicates predicates("test1");
|
||||
predicates.EqualTo("id", 1);
|
||||
int ret = store->Delete(changedRows, predicates);
|
||||
EXPECT_EQ(ret, E_OK);
|
||||
EXPECT_EQ(changedRows, 1);
|
||||
|
||||
std::shared_ptr<ResultSet> resultSet =
|
||||
store->QuerySql("SELECT * FROM test1 where name = 'lisi_update1'");
|
||||
EXPECT_NE(resultSet, nullptr);
|
||||
int count = 0;
|
||||
resultSet->GetRowCount(count);
|
||||
EXPECT_EQ(0, count);
|
||||
|
||||
int changedRows2 = 0;
|
||||
AbsRdbPredicates predicates2("test2");
|
||||
predicates2.EqualTo("id", 1);
|
||||
ret = store->Delete(changedRows2, predicates2);
|
||||
EXPECT_EQ(ret, E_OK);
|
||||
EXPECT_EQ(changedRows2, 1);
|
||||
|
||||
std::shared_ptr<ResultSet> resultSet2 =
|
||||
store->QuerySql("SELECT * FROM test2 where name = 'lisi_update2'");
|
||||
EXPECT_NE(resultSet2, nullptr);
|
||||
int count2 = 0;
|
||||
resultSet2->GetRowCount(count2);
|
||||
EXPECT_EQ(0, count2);
|
||||
}
|
||||
|
||||
void RdbAttachTest::UpdateCheck(std::shared_ptr<RdbStore> &store) const
|
||||
{
|
||||
int changedRows = 0;
|
||||
ValuesBucket values;
|
||||
values.PutString("name", std::string("lisi_update1"));
|
||||
AbsRdbPredicates predicates("test1");
|
||||
predicates.EqualTo("id", 1);
|
||||
int ret = store->Update(changedRows, values, predicates);
|
||||
EXPECT_EQ(ret, E_OK);
|
||||
EXPECT_EQ(changedRows, 1);
|
||||
|
||||
std::shared_ptr<ResultSet> resultSet =
|
||||
store->QuerySql("SELECT * FROM test1 where name = 'lisi_update1'");
|
||||
EXPECT_NE(resultSet, nullptr);
|
||||
int count = 0;
|
||||
resultSet->GetRowCount(count);
|
||||
EXPECT_EQ(1, count);
|
||||
|
||||
values.Clear();
|
||||
values.PutString("name", std::string("lisi_update2"));
|
||||
AbsRdbPredicates predicates2("test2");
|
||||
predicates2.EqualTo("id", 1);
|
||||
int changedRows2 = 0;
|
||||
ret = store->Update(changedRows2, values, predicates2);
|
||||
EXPECT_EQ(ret, E_OK);
|
||||
EXPECT_EQ(changedRows2, 1);
|
||||
|
||||
std::shared_ptr<ResultSet> resultSet2 =
|
||||
store->QuerySql("SELECT * FROM test2 where name = 'lisi_update2'");
|
||||
EXPECT_NE(resultSet2, nullptr);
|
||||
int count2 = 0;
|
||||
resultSet2->GetRowCount(count2);
|
||||
EXPECT_EQ(1, count2);
|
||||
}
|
||||
|
||||
void RdbAttachTest::InsertCheck(std::shared_ptr<RdbStore> &store) const
|
||||
{
|
||||
int64_t id;
|
||||
ValuesBucket values;
|
||||
values.PutInt("id", 1);
|
||||
values.PutString("name", std::string("zhangsan"));
|
||||
int ret = store->Insert(id, "test1", values);
|
||||
EXPECT_EQ(ret, E_OK);
|
||||
EXPECT_EQ(id, 1);
|
||||
|
||||
values.Clear();
|
||||
values.PutInt("id", 1);
|
||||
values.PutString("name", std::string("lisi"));
|
||||
ret = store->Insert(id, "test2", values);
|
||||
EXPECT_EQ(ret, E_OK);
|
||||
EXPECT_EQ(id, 1);
|
||||
}
|
||||
|
@ -205,7 +205,7 @@ HWTEST_F(RdbStoreConfigTest, RdbStoreConfig_003, TestSize.Level1)
|
||||
ConfigTestOpenCallback helper;
|
||||
std::shared_ptr<RdbStore> store = RdbHelper::GetRdbStore(config, 1, helper, errCode);
|
||||
EXPECT_EQ(store, nullptr);
|
||||
EXPECT_EQ(errCode, E_EMPTY_FILE_NAME);
|
||||
EXPECT_EQ(errCode, E_INVALID_FILE_PATH);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -221,7 +221,7 @@ HWTEST_F(RdbStoreConfigTest, RdbStoreConfig_004, TestSize.Level1)
|
||||
ConfigTestOpenCallback helper;
|
||||
std::shared_ptr<RdbStore> store = RdbHelper::GetRdbStore(config, 1, helper, errCode);
|
||||
EXPECT_EQ(store, nullptr);
|
||||
EXPECT_EQ(errCode, E_RELATIVE_PATH);
|
||||
EXPECT_EQ(errCode, E_INVALID_FILE_PATH);
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
x
Reference in New Issue
Block a user