feature:add createTransacion

Signed-off-by: htt1997 <hutao105@huawei.com>
This commit is contained in:
htt1997 2024-11-18 15:28:34 +08:00
parent a48812841f
commit ba4faabcc4
77 changed files with 10603 additions and 3344 deletions

View File

@ -700,7 +700,11 @@ napi_value RdbStoreProxy::Query(napi_env env, napi_callback_info info)
auto exec = [context]() {
RdbStoreProxy *obj = reinterpret_cast<RdbStoreProxy *>(context->boundObj);
CHECK_RETURN_ERR(obj != nullptr && obj->rdbStore_ != nullptr);
#if defined(WINDOWS_PLATFORM) || defined(MAC_PLATFORM) || defined(ANDROID_PLATFORM) || defined(IOS_PLATFORM)
context->resultSet = obj->rdbStore_->QueryByStep(*(context->rdbPredicates), context->columns);
#else
context->resultSet = obj->rdbStore_->Query(*(context->rdbPredicates), context->columns);
#endif
LOG_DEBUG("RdbStoreProxy::Query result is nullptr ? %{public}d.", (context->resultSet == nullptr));
return (context->resultSet != nullptr) ? OK : ERR;
};

View File

@ -36,6 +36,7 @@ sources = [
"src/napi_rdb_store.cpp",
"src/napi_rdb_store_helper.cpp",
"src/napi_result_set.cpp",
"src/napi_transaction.cpp",
"src/napi_uv_queue.cpp",
]

View File

@ -17,7 +17,9 @@
#define NAPI_RDB_CONTEXT_H
#include "napi_async_call.h"
#include "napi_rdb_js_utils.h"
#include "napi_rdb_predicates.h"
#include "transaction.h"
#include "values_buckets.h"
namespace OHOS {
@ -25,6 +27,12 @@ namespace RelationalStoreJsKit {
class ResultSetProxy;
using namespace OHOS::NativeRdb;
struct RdbStoreContextBase : public ContextBase {
std::shared_ptr<NativeRdb::RdbStore> StealRdbStore()
{
auto rdb = std::move(rdbStore);
rdbStore = nullptr;
return rdb;
}
std::shared_ptr<NativeRdb::RdbStore> rdbStore = nullptr;
};
@ -75,6 +83,11 @@ struct RdbStoreContext : public RdbStoreContextBase {
{
}
};
struct CreateTransactionContext : public RdbStoreContextBase {
AppDataMgrJsKit::JSUtils::TransactionOptions transactionOptions;
std::shared_ptr<Transaction> transaction;
};
} // namespace RelationalStoreJsKit
} // namespace OHOS
#endif // NAPI_RDB_CONTEXT_H

View File

@ -70,6 +70,10 @@ struct ContextParam {
bool isStageMode = true;
};
struct TransactionOptions {
int32_t transactionType = 0;
};
template<>
int32_t Convert2Value(napi_env env, napi_value input, Asset &output);
@ -85,6 +89,9 @@ 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, TransactionOptions &transactionOptions);
template<>
int32_t Convert2Value(napi_env env, napi_value jsValue, ContextParam &context);

View File

@ -61,7 +61,6 @@ private:
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);
static napi_value IsReadOnly(napi_env env, napi_callback_info info);
static napi_value BeginTransaction(napi_env env, napi_callback_info info);
static napi_value BeginTrans(napi_env env, napi_callback_info info);
@ -70,7 +69,6 @@ private:
static napi_value Commit(napi_env env, napi_callback_info info);
static napi_value QueryByStep(napi_env env, napi_callback_info info);
static napi_value IsInTransaction(napi_env env, napi_callback_info info);
static napi_value IsOpen(napi_env env, napi_callback_info info);
static napi_value GetVersion(napi_env env, napi_callback_info info);
static napi_value GetRebuilt(napi_env env, napi_callback_info info);
static napi_value SetVersion(napi_env env, napi_callback_info info);
@ -86,6 +84,7 @@ private:
static napi_value Notify(napi_env env, napi_callback_info info);
static napi_value QuerySharingResource(napi_env env, napi_callback_info info);
static napi_value Close(napi_env env, napi_callback_info info);
static napi_value CreateTransaction(napi_env env, napi_callback_info info);
static Descriptor GetDescriptors();
static void AddSyncFunctions(std::vector<napi_property_descriptor> &properties);
static napi_value ModifyLockStatus(napi_env env, napi_callback_info info, bool isLock);

View File

@ -0,0 +1,52 @@
/*
* Copyright (c) 2024 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef RDB_JSKIT_NAPI_TRANSACTION_H
#define RDB_JSKIT_NAPI_TRANSACTION_H
#include <memory>
#include "js_proxy.h"
#include "napi/native_api.h"
#include "napi/native_common.h"
#include "napi/native_node_api.h"
#include "transaction.h"
namespace OHOS {
namespace RelationalStoreJsKit {
class TransactionProxy final : public JSProxy::JSProxy<NativeRdb::Transaction> {
public:
TransactionProxy() = default;
~TransactionProxy();
TransactionProxy(std::shared_ptr<NativeRdb::Transaction> transaction);
static void Init(napi_env env, napi_value exports);
static napi_value NewInstance(napi_env env, std::shared_ptr<NativeRdb::Transaction> transaction);
private:
static napi_value Initialize(napi_env env, napi_callback_info info);
static napi_value Commit(napi_env env, napi_callback_info info);
static napi_value Rollback(napi_env env, napi_callback_info info);
static napi_value Delete(napi_env env, napi_callback_info info);
static napi_value Update(napi_env env, napi_callback_info info);
static napi_value Insert(napi_env env, napi_callback_info info);
static napi_value BatchInsert(napi_env env, napi_callback_info info);
static napi_value Query(napi_env env, napi_callback_info info);
static napi_value QuerySql(napi_env env, napi_callback_info info);
static napi_value Execute(napi_env env, napi_callback_info info);
static void AddSyncFunctions(std::vector<napi_property_descriptor> &properties);
};
} // namespace RelationalStoreJsKit
} // namespace OHOS
#endif // RDB_JSKIT_NAPI_TRANSACTION_H

View File

@ -75,6 +75,7 @@ private:
static napi_value SetVersion(napi_env env, napi_callback_info info);
static napi_value Restore(napi_env env, napi_callback_info info);
static napi_value Close(napi_env env, napi_callback_info info);
static napi_value CreateTransaction(napi_env env, napi_callback_info info);
int32_t dbType = NativeRdb::DB_SQLITE;
std::mutex mutex_;

View File

@ -18,6 +18,7 @@
#include "napi_rdb_store_helper.h"
#include "napi_rdb_const_properties.h"
#include "napi_result_set.h"
#include "napi_transaction.h"
#include "napi/native_api.h"
using namespace OHOS::RelationalStoreJsKit;
@ -32,6 +33,7 @@ static napi_value Init(napi_env env, napi_value exports)
RdbStoreProxy::Init(env, exports);
RdbPredicatesProxy::Init(env, exports);
ResultSetProxy::Init(env, exports);
TransactionProxy::Init(env, exports);
InitConstProperties(env, exports);
return exports;
}

View File

@ -211,6 +211,19 @@ static napi_value ExportHAMode(napi_env env)
return haMode;
}
static napi_value ExportTransactionType(napi_env env)
{
napi_value transactionType = nullptr;
napi_create_object(env, &transactionType);
SET_NAPI_PROPERTY(transactionType, "DEFERRED", int32_t(NativeRdb::Transaction::DEFERRED));
SET_NAPI_PROPERTY(transactionType, "IMMEDIATE", int32_t(NativeRdb::Transaction::IMMEDIATE));
SET_NAPI_PROPERTY(transactionType, "EXCLUSIVE", int32_t(NativeRdb::Transaction::EXCLUSIVE));
napi_object_freeze(env, transactionType);
return transactionType;
}
napi_status InitConstProperties(napi_env env, napi_value exports)
{
const napi_property_descriptor properties[] = {
@ -229,6 +242,7 @@ napi_status InitConstProperties(napi_env env, napi_value exports)
DECLARE_NAPI_PROPERTY("Field", ExportField(env)),
DECLARE_NAPI_PROPERTY("RebuildType", ExportRebuiltType(env)),
DECLARE_NAPI_PROPERTY("HAMode", ExportHAMode(env)),
DECLARE_NAPI_PROPERTY("TransactionType", ExportTransactionType(env)),
};
size_t count = sizeof(properties) / sizeof(properties[0]);

View File

@ -26,6 +26,7 @@
#include "rdb_sql_utils.h"
#include "rdb_types.h"
#include "result_set.h"
#include "transaction.h"
#define NAPI_CALL_RETURN_ERR(theCall, retVal) \
do { \
@ -358,6 +359,16 @@ int32_t Convert2Value(napi_env env, napi_value jsValue, RdbConfig &rdbConfig)
return napi_ok;
}
template<>
int32_t Convert2Value(napi_env env, napi_value jsValue, TransactionOptions &transactionOptions)
{
int32_t status = GetNamedProperty(env, jsValue, "transactionType", transactionOptions.transactionType, true);
bool checked = transactionOptions.transactionType >= Transaction::DEFERRED &&
transactionOptions.transactionType <= Transaction::EXCLUSIVE;
ASSERT(OK == status && checked, "get transactionType failed.", napi_invalid_arg);
return napi_ok;
}
int32_t GetCurrentAbilityParam(napi_env env, napi_value jsValue, ContextParam &param)
{
std::shared_ptr<Context> context = JSAbility::GetCurrentAbility(env, jsValue);

View File

@ -31,6 +31,7 @@
#include "napi_rdb_js_utils.h"
#include "napi_rdb_trace.h"
#include "napi_result_set.h"
#include "napi_transaction.h"
#include "rdb_errno.h"
#include "rdb_sql_statistic.h"
#include "securec.h"
@ -162,6 +163,7 @@ Descriptor RdbStoreProxy::GetDescriptors()
DECLARE_NAPI_FUNCTION("close", Close),
DECLARE_NAPI_FUNCTION("attach", Attach),
DECLARE_NAPI_FUNCTION("detach", Detach),
DECLARE_NAPI_FUNCTION("createTransaction", CreateTransaction),
#if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM)
DECLARE_NAPI_FUNCTION("remoteQuery", RemoteQuery),
DECLARE_NAPI_FUNCTION("setDistributedTables", SetDistributedTables),
@ -266,7 +268,7 @@ RdbStoreProxy *GetNativeInstance(napi_env env, napi_value self)
RdbStoreProxy *proxy = nullptr;
napi_status status = napi_unwrap(env, self, reinterpret_cast<void **>(&proxy));
if (proxy == nullptr) {
LOG_ERROR("RdbStoreProxy::GetNativePredicates native instance is nullptr! code:%{public}d!", status);
LOG_ERROR("RdbStoreProxy native instance is nullptr! code:%{public}d!", status);
return nullptr;
}
return proxy;
@ -439,20 +441,6 @@ int ParseColumns(const napi_env env, const napi_value arg, std::shared_ptr<RdbSt
return OK;
}
int ParseAlias(const napi_env env, const napi_value arg, std::shared_ptr<RdbStoreContext> context)
{
context->aliasName = JSUtils::Convert2String(env, arg);
CHECK_RETURN_SET(!context->aliasName.empty(), std::make_shared<ParamError>("aliasName", "not empty"));
return OK;
}
int ParsePath(const napi_env env, const napi_value arg, std::shared_ptr<RdbStoreContext> context)
{
context->pathName = JSUtils::Convert2String(env, arg);
CHECK_RETURN_SET(!context->pathName.empty(), std::make_shared<ParamError>("pathName", "not empty"));
return OK;
}
int ParseBindArgs(const napi_env env, const napi_value arg, std::shared_ptr<RdbStoreContext> context)
{
context->bindArgs.clear();
@ -645,6 +633,17 @@ napi_value RdbStoreProxy::Insert(napi_env env, napi_callback_info info)
return ASYNC_CALL(env, context);
}
int ParseTransactionOptions(
const napi_env &env, size_t argc, napi_value *argv, std::shared_ptr<CreateTransactionContext> context)
{
context->transactionOptions.transactionType = Transaction::DEFERRED;
if (argc > 0 && !JSUtils::IsNull(env, argv[0])) {
auto status = JSUtils::Convert2Value(env, argv[0], context->transactionOptions);
CHECK_RETURN_SET(status == napi_ok, std::make_shared<ParamError>("options", "a transactionOptions"));
}
return OK;
}
napi_value RdbStoreProxy::BatchInsert(napi_env env, napi_callback_info info)
{
auto context = std::make_shared<RdbStoreContext>();
@ -762,7 +761,11 @@ napi_value RdbStoreProxy::Query(napi_env env, napi_callback_info info)
};
auto exec = [context]() -> int {
CHECK_RETURN_ERR(context->rdbStore != nullptr && context->rdbPredicates != nullptr);
#if defined(WINDOWS_PLATFORM) || defined(MAC_PLATFORM) || defined(ANDROID_PLATFORM) || defined(IOS_PLATFORM)
context->resultSet = context->rdbStore->QueryByStep(*(context->rdbPredicates), context->columns);
#else
context->resultSet = context->rdbStore->Query(*(context->rdbPredicates), context->columns);
#endif
context->rdbStore = nullptr;
return (context->resultSet != nullptr) ? E_OK : E_ERROR;
};
@ -1080,18 +1083,6 @@ napi_value RdbStoreProxy::IsReadOnly(napi_env env, napi_callback_info info)
return JSUtils::Convert2JSValue(env, out);
}
napi_value RdbStoreProxy::IsMemoryRdb(napi_env env, napi_callback_info info)
{
napi_value thisObj = nullptr;
napi_get_cb_info(env, info, nullptr, nullptr, &thisObj, nullptr);
RdbStoreProxy *rdbStoreProxy = GetNativeInstance(env, thisObj);
RDB_NAPI_ASSERT(env, rdbStoreProxy != nullptr && rdbStoreProxy->GetInstance() != nullptr,
std::make_shared<ParamError>("RdbStore", "valid"));
bool out = rdbStoreProxy->GetInstance()->IsMemoryRdb();
LOG_DEBUG("RdbStoreProxy::IsMemoryRdb out is : %{public}d", out);
return JSUtils::Convert2JSValue(env, out);
}
napi_value RdbStoreProxy::GetPath(napi_env env, napi_callback_info info)
{
napi_value thisObj = nullptr;
@ -1255,32 +1246,6 @@ napi_value RdbStoreProxy::QueryByStep(napi_env env, napi_callback_info info)
return ASYNC_CALL(env, context);
}
napi_value RdbStoreProxy::IsInTransaction(napi_env env, napi_callback_info info)
{
napi_value thisObj = nullptr;
napi_get_cb_info(env, info, nullptr, nullptr, &thisObj, nullptr);
RdbStoreProxy *rdbStoreProxy = GetNativeInstance(env, thisObj);
RDB_NAPI_ASSERT(env, rdbStoreProxy != nullptr, std::make_shared<ParamError>("RdbStore", "valid"));
RDB_NAPI_ASSERT(
env, rdbStoreProxy->GetInstance() != nullptr, std::make_shared<InnerError>(NativeRdb::E_ALREADY_CLOSED));
bool out = rdbStoreProxy->GetInstance()->IsInTransaction();
LOG_DEBUG("RdbStoreProxy::IsInTransaction out is : %{public}d", out);
return JSUtils::Convert2JSValue(env, out);
}
napi_value RdbStoreProxy::IsOpen(napi_env env, napi_callback_info info)
{
napi_value thisObj = nullptr;
napi_get_cb_info(env, info, nullptr, nullptr, &thisObj, nullptr);
RdbStoreProxy *rdbStoreProxy = GetNativeInstance(env, thisObj);
RDB_NAPI_ASSERT(env, rdbStoreProxy != nullptr, std::make_shared<ParamError>("RdbStore", "valid"));
RDB_NAPI_ASSERT(
env, rdbStoreProxy->GetInstance() != nullptr, std::make_shared<InnerError>(NativeRdb::E_ALREADY_CLOSED));
bool out = rdbStoreProxy->GetInstance()->IsOpen();
LOG_DEBUG("RdbStoreProxy::IsOpen out is : %{public}d", out);
return JSUtils::Convert2JSValue(env, out);
}
napi_value RdbStoreProxy::GetVersion(napi_env env, napi_callback_info info)
{
napi_value thisObj = nullptr;
@ -2195,5 +2160,33 @@ napi_value RdbStoreProxy::Close(napi_env env, napi_callback_info info)
CHECK_RETURN_NULL(context->error == nullptr || context->error->GetCode() == OK);
return ASYNC_CALL(env, context);
}
napi_value RdbStoreProxy::CreateTransaction(napi_env env, napi_callback_info info)
{
auto context = std::make_shared<CreateTransactionContext>();
auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) {
CHECK_RETURN(OK == ParserThis(env, self, context));
CHECK_RETURN(OK == ParseTransactionOptions(env, argc, argv, context));
};
auto exec = [context]() -> int {
CHECK_RETURN_ERR(context->rdbStore != nullptr);
int32_t code = E_ERROR;
std::tie(code, context->transaction) =
context->StealRdbStore()->CreateTransaction(context->transactionOptions.transactionType);
if (code != E_OK) {
context->transaction = nullptr;
return code;
}
return context->transaction != nullptr ? OK : E_ERROR;
};
auto output = [context](napi_env env, napi_value &result) {
result = TransactionProxy::NewInstance(env, context->transaction);
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 ASYNC_CALL(env, context);
}
} // namespace RelationalStoreJsKit
} // namespace OHOS

View File

@ -0,0 +1,670 @@
/*
* Copyright (c) 2024 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define LOG_TAG "TransactionProxy"
#include "napi_transaction.h"
#include "js_utils.h"
#include "napi_async_call.h"
#include "napi_rdb_error.h"
#include "napi_rdb_js_utils.h"
#include "napi_rdb_predicates.h"
#include "napi_result_set.h"
#include "rdb_common.h"
#include "rdb_errno.h"
using namespace OHOS::Rdb;
using namespace OHOS::NativeRdb;
using namespace OHOS::AppDataMgrJsKit;
namespace OHOS::RelationalStoreJsKit {
#define ASSERT_RETURN_SET_ERROR(assertion, paramError) \
CHECK_RETURN_CORE(assertion, SetError(paramError), ERR)
struct TransactionContext : public ContextBase {
void GetInstance(napi_value self)
{
auto status = napi_unwrap(env_, self, reinterpret_cast<void **>(&boundObj));
if (status != napi_ok || boundObj == nullptr) {
LOG_ERROR("TransactionProxy native instance is nullptr! code:%{public}d!", status);
return;
}
transaction_ = reinterpret_cast<TransactionProxy *>(boundObj)->GetInstance();
}
std::shared_ptr<NativeRdb::Transaction> StealTransaction()
{
auto trans = std::move(transaction_);
transaction_ = nullptr;
return trans;
}
int32_t ParseRdbPredicatesProxy(napi_env env, napi_value arg, std::shared_ptr<RdbPredicates> &predicates);
int32_t ParseSendableValuesBucket(napi_env env, napi_value arg, ValuesBucket &valuesBucket);
int32_t ParseValuesBucket(napi_env env, napi_value arg, ValuesBucket &valuesBucket);
int32_t ParseValuesBuckets(napi_env env, napi_value arg, std::vector<ValuesBucket> &valuesBuckets);
int32_t ParseConflictResolution(napi_env env, napi_value arg, NativeRdb::ConflictResolution &conflictResolution);
std::shared_ptr<NativeRdb::Transaction> transaction_ = nullptr;
static constexpr int32_t KEY_INDEX = 0;
static constexpr int32_t VALUE_INDEX = 1;
};
int32_t TransactionContext::ParseRdbPredicatesProxy(
napi_env env, napi_value arg, std::shared_ptr<RdbPredicates> &predicates)
{
RdbPredicatesProxy *predicatesProxy = nullptr;
auto status = napi_unwrap(env, arg, reinterpret_cast<void **>(&predicatesProxy));
ASSERT_RETURN_SET_ERROR(status == napi_ok && predicatesProxy != nullptr,
std::make_shared<ParamError>("predicates", "an RdbPredicates."));
predicates = predicatesProxy->GetInstance();
ASSERT_RETURN_SET_ERROR(predicates != nullptr, std::make_shared<ParamError>("predicates", "an RdbPredicates."));
return OK;
}
int32_t TransactionContext::ParseSendableValuesBucket(
const napi_env env, const napi_value map, ValuesBucket &valuesBucket)
{
uint32_t length = 0;
napi_status status = napi_map_get_size(env, map, &length);
auto error = std::make_shared<ParamError>("ValuesBucket is invalid.");
ASSERT_RETURN_SET_ERROR(status == napi_ok && length > 0, error);
napi_value entries = nullptr;
status = napi_map_get_entries(env, map, &entries);
ASSERT_RETURN_SET_ERROR(status == napi_ok, std::make_shared<InnerError>("napi_map_get_entries failed."));
for (uint32_t i = 0; i < length; ++i) {
napi_value iter = nullptr;
status = napi_map_iterator_get_next(env, entries, &iter);
ASSERT_RETURN_SET_ERROR(status == napi_ok, std::make_shared<InnerError>("napi_map_iterator_get_next failed."));
napi_value values = nullptr;
status = napi_get_named_property(env, iter, "value", &values);
ASSERT_RETURN_SET_ERROR(
status == napi_ok, std::make_shared<InnerError>("napi_get_named_property value failed."));
napi_value key = nullptr;
status = napi_get_element(env, values, KEY_INDEX, &key);
ASSERT_RETURN_SET_ERROR(status == napi_ok, std::make_shared<InnerError>("napi_get_element key failed."));
std::string keyStr = JSUtils::Convert2String(env, key);
napi_value value = nullptr;
status = napi_get_element(env, values, VALUE_INDEX, &value);
ASSERT_RETURN_SET_ERROR(status == napi_ok, std::make_shared<InnerError>("napi_get_element value failed."));
ValueObject valueObject;
int32_t ret = JSUtils::Convert2Value(env, value, valueObject.value);
if (ret == napi_ok) {
valuesBucket.values_.insert_or_assign(std::move(keyStr), std::move(valueObject));
} else if (ret != napi_generic_failure) {
ASSERT_RETURN_SET_ERROR(false, std::make_shared<ParamError>("The value type of " + keyStr, "invalid."));
}
}
return OK;
}
int32_t TransactionContext::ParseValuesBucket(napi_env env, napi_value arg, ValuesBucket &valuesBucket)
{
bool isMap = false;
napi_status status = napi_is_map(env, arg, &isMap);
ASSERT_RETURN_SET_ERROR(
status == napi_ok, std::make_shared<InnerError>("call napi_is_map failed" + std::to_string(status)));
if (isMap) {
return ParseSendableValuesBucket(env, arg, valuesBucket);
}
napi_value keys = nullptr;
napi_get_all_property_names(env, arg, napi_key_own_only,
static_cast<napi_key_filter>(napi_key_enumerable | napi_key_skip_symbols), napi_key_numbers_to_strings, &keys);
uint32_t arrLen = 0;
status = napi_get_array_length(env, keys, &arrLen);
ASSERT_RETURN_SET_ERROR(status == napi_ok && arrLen > 0, std::make_shared<ParamError>("ValuesBucket is invalid"));
for (size_t i = 0; i < arrLen; ++i) {
napi_value key = nullptr;
status = napi_get_element(env, keys, i, &key);
ASSERT_RETURN_SET_ERROR(status == napi_ok, std::make_shared<ParamError>("ValuesBucket is invalid."));
std::string keyStr = JSUtils::Convert2String(env, key);
napi_value value = nullptr;
napi_get_property(env, arg, key, &value);
ValueObject valueObject;
int32_t ret = JSUtils::Convert2Value(env, value, valueObject.value);
if (ret == napi_ok) {
valuesBucket.values_.insert_or_assign(std::move(keyStr), std::move(valueObject));
} else if (ret != napi_generic_failure) {
ASSERT_RETURN_SET_ERROR(false, std::make_shared<ParamError>("The value type of " + keyStr, "invalid."));
}
}
return OK;
}
int32_t TransactionContext::ParseValuesBuckets(napi_env env, napi_value arg, std::vector<ValuesBucket> &valuesBuckets)
{
bool isArray = false;
auto status = napi_is_array(env, arg, &isArray);
ASSERT_RETURN_SET_ERROR(status == napi_ok && isArray, std::make_shared<ParamError>("ValuesBucket is invalid."));
uint32_t arrLen = 0;
status = napi_get_array_length(env, arg, &arrLen);
ASSERT_RETURN_SET_ERROR(status == napi_ok && arrLen > 0, std::make_shared<ParamError>("ValuesBucket is invalid."));
for (uint32_t i = 0; i < arrLen; ++i) {
napi_value obj = nullptr;
status = napi_get_element(env, arg, i, &obj);
ASSERT_RETURN_SET_ERROR(status == napi_ok, std::make_shared<InnerError>("napi_get_element failed."));
ValuesBucket valuesBucket;
ASSERT_RETURN_SET_ERROR(
ParseValuesBucket(env, obj, valuesBucket) == OK, std::make_shared<ParamError>("ValuesBucket is invalid."));
valuesBuckets.push_back(std::move(valuesBucket));
}
return OK;
}
int32_t TransactionContext::ParseConflictResolution(
const napi_env env, const napi_value arg, NativeRdb::ConflictResolution &conflictResolution)
{
int32_t input = 0;
auto status = napi_get_value_int32(env, arg, &input);
int min = static_cast<int32_t>(NativeRdb::ConflictResolution::ON_CONFLICT_NONE);
int max = static_cast<int32_t>(NativeRdb::ConflictResolution::ON_CONFLICT_REPLACE);
bool checked = status == napi_ok && (input >= min) && (input <= max);
ASSERT_RETURN_SET_ERROR(checked, std::make_shared<ParamError>("conflictResolution", "a ConflictResolution."));
conflictResolution = static_cast<NativeRdb::ConflictResolution>(input);
return OK;
}
napi_value TransactionProxy::NewInstance(napi_env env, std::shared_ptr<NativeRdb::Transaction> transaction)
{
napi_value cons = JSUtils::GetClass(env, "ohos.data.relationalStore", "Transaction");
if (cons == nullptr) {
LOG_ERROR("Constructor of Transaction is nullptr!");
return nullptr;
}
napi_value instance = nullptr;
auto status = napi_new_instance(env, cons, 0, nullptr, &instance);
if (status != napi_ok) {
LOG_ERROR("NewInstance napi_new_instance failed! code:%{public}d!", status);
return nullptr;
}
TransactionProxy *proxy = nullptr;
status = napi_unwrap(env, instance, reinterpret_cast<void **>(&proxy));
if (proxy == nullptr) {
LOG_ERROR("NewInstance native instance is nullptr! code:%{public}d!", status);
return instance;
}
proxy->SetInstance(std::move(transaction));
return instance;
}
void TransactionProxy::Init(napi_env env, napi_value exports)
{
auto lambda = []() -> std::vector<napi_property_descriptor> {
std::vector<napi_property_descriptor> properties = {
DECLARE_NAPI_FUNCTION("rollback", Rollback),
DECLARE_NAPI_FUNCTION("commit", Commit),
DECLARE_NAPI_FUNCTION_WITH_DATA("delete", Delete, ASYNC),
DECLARE_NAPI_FUNCTION_WITH_DATA("update", Update, ASYNC),
DECLARE_NAPI_FUNCTION_WITH_DATA("insert", Insert, ASYNC),
DECLARE_NAPI_FUNCTION_WITH_DATA("batchInsert", BatchInsert, ASYNC),
DECLARE_NAPI_FUNCTION_WITH_DATA("query", Query, ASYNC),
DECLARE_NAPI_FUNCTION_WITH_DATA("querySql", QuerySql, ASYNC),
DECLARE_NAPI_FUNCTION_WITH_DATA("execute", Execute, ASYNC),
};
AddSyncFunctions(properties);
return properties;
};
auto jsCtor = JSUtils::DefineClass(env, "ohos.data.relationalStore", "Transaction", lambda, Initialize);
NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, exports, "Transaction", jsCtor));
LOG_DEBUG("TransactionProxy::Init end.");
}
void TransactionProxy::AddSyncFunctions(std::vector<napi_property_descriptor> &properties)
{
properties.push_back(DECLARE_NAPI_FUNCTION_WITH_DATA("deleteSync", Delete, SYNC));
properties.push_back(DECLARE_NAPI_FUNCTION_WITH_DATA("updateSync", Update, SYNC));
properties.push_back(DECLARE_NAPI_FUNCTION_WITH_DATA("insertSync", Insert, SYNC));
properties.push_back(DECLARE_NAPI_FUNCTION_WITH_DATA("batchInsertSync", BatchInsert, SYNC));
properties.push_back(DECLARE_NAPI_FUNCTION_WITH_DATA("querySync", Query, SYNC));
properties.push_back(DECLARE_NAPI_FUNCTION_WITH_DATA("querySqlSync", QuerySql, SYNC));
properties.push_back(DECLARE_NAPI_FUNCTION_WITH_DATA("executeSync", Execute, SYNC));
}
TransactionProxy::~TransactionProxy()
{
}
TransactionProxy::TransactionProxy(std::shared_ptr<NativeRdb::Transaction> transaction)
{
if (GetInstance() == transaction) {
return;
}
SetInstance(std::move(transaction));
}
napi_value TransactionProxy::Initialize(napi_env env, napi_callback_info info)
{
napi_value self = nullptr;
NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &self, nullptr));
auto *proxy = new (std::nothrow) TransactionProxy();
if (proxy == nullptr) {
LOG_ERROR("no memory, new TransactionProxy failed!");
return nullptr;
}
auto finalize = [](napi_env env, void *data, void *hint) {
if (data != hint) {
LOG_ERROR("memory corrupted! data:0x%016" PRIXPTR "hint:0x%016" PRIXPTR, uintptr_t(data),
uintptr_t(hint));
return;
}
TransactionProxy *proxy = reinterpret_cast<TransactionProxy *>(data);
proxy->SetInstance(nullptr);
delete proxy;
};
napi_status status = napi_wrap(env, self, proxy, finalize, proxy, nullptr);
if (status != napi_ok) {
LOG_ERROR("napi_wrap failed! code:%{public}d!", status);
finalize(env, proxy, proxy);
return nullptr;
}
return self;
}
struct CommitContext : public TransactionContext {
int32_t Parse(napi_env env, size_t argc, napi_value *argv, napi_value self)
{
GetInstance(self);
ASSERT_RETURN_SET_ERROR(
transaction_ != nullptr, std::make_shared<ParamError>("transaction", "a transaction."));
return OK;
}
};
/*
* [JS API Prototype]
* [Promise]
* commit(): Promise<void>;
*/
napi_value TransactionProxy::Commit(napi_env env, napi_callback_info info)
{
auto context = std::make_shared<CommitContext>();
auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) {
context->Parse(env, argc, argv, self);
};
auto exec = [context]() -> int {
CHECK_RETURN_ERR(context->transaction_ != nullptr);
return context->StealTransaction()->Commit();
};
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));
};
context->SetAction(env, info, input, exec, output);
CHECK_RETURN_NULL(context->error == nullptr || context->error->GetCode() == OK);
return ASYNC_CALL(env, context);
}
struct RollbackContext : public TransactionContext {
int32_t Parse(napi_env env, size_t argc, napi_value *argv, napi_value self)
{
GetInstance(self);
ASSERT_RETURN_SET_ERROR(
transaction_ != nullptr, std::make_shared<ParamError>("transaction", "a transaction."));
return OK;
}
};
/*
* [JS API Prototype]
* [Promise]
* rollback(): Promise<void>;
*/
napi_value TransactionProxy::Rollback(napi_env env, napi_callback_info info)
{
auto context = std::make_shared<RollbackContext>();
auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) {
context->Parse(env, argc, argv, self);
};
auto exec = [context]() -> int {
CHECK_RETURN_ERR(context->transaction_ != nullptr);
return context->StealTransaction()->Rollback();
};
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));
};
context->SetAction(env, info, input, exec, output);
CHECK_RETURN_NULL(context->error == nullptr || context->error->GetCode() == OK);
return ASYNC_CALL(env, context);
}
struct DeleteContext : public TransactionContext {
int32_t Parse(napi_env env, size_t argc, napi_value *argv, napi_value self)
{
ASSERT_RETURN_SET_ERROR(argc == 1, std::make_shared<ParamNumError>("1"));
GetInstance(self);
ASSERT_RETURN_SET_ERROR(
transaction_ != nullptr, std::make_shared<ParamError>("transaction", "a transaction."));
CHECK_RETURN_ERR(ParseRdbPredicatesProxy(env, argv[0], rdbPredicates) == OK);
return OK;
}
std::shared_ptr<RdbPredicates> rdbPredicates = nullptr;
int64_t deleteRows = -1;
};
/*
* [JS API Prototype]
* [Promise]
* delete(predicates: RdbPredicates): Promise<number>;
*/
napi_value TransactionProxy::Delete(napi_env env, napi_callback_info info)
{
auto context = std::make_shared<DeleteContext>();
auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) {
context->Parse(env, argc, argv, self);
};
auto exec = [context]() -> int {
CHECK_RETURN_ERR(context->transaction_ != nullptr && context->rdbPredicates != nullptr);
auto [code, deleteRows] = context->StealTransaction()->Delete(*(context->rdbPredicates));
context->deleteRows = deleteRows;
return code;
};
auto output = [context](napi_env env, napi_value &result) {
napi_status status = napi_create_int64(env, context->deleteRows, &result);
CHECK_RETURN_SET_E(status == napi_ok, std::make_shared<InnerError>(E_ERROR));
};
context->SetAction(env, info, input, exec, output);
CHECK_RETURN_NULL(context->error == nullptr || context->error->GetCode() == OK);
return ASYNC_CALL(env, context);
}
struct UpdateContext : public TransactionContext {
int32_t Parse(napi_env env, size_t argc, napi_value *argv, napi_value self)
{
ASSERT_RETURN_SET_ERROR(argc == 2 || argc == 3, std::make_shared<ParamNumError>("2 to 3"));
GetInstance(self);
ASSERT_RETURN_SET_ERROR(
transaction_ != nullptr, std::make_shared<ParamError>("transaction", "a transaction."));
CHECK_RETURN_ERR(ParseValuesBucket(env, argv[0], valuesBucket) == OK);
CHECK_RETURN_ERR(ParseRdbPredicatesProxy(env, argv[1], rdbPredicates) == OK);
// 'argv[2]' is an optional parameter
if (argc > 2 && !JSUtils::IsNull(env, argv[2])) {
// 'argv[2]' represents a ConflictResolution parameter
CHECK_RETURN_ERR(ParseConflictResolution(env, argv[2], conflictResolution));
}
return OK;
}
ValuesBucket valuesBucket;
std::shared_ptr<RdbPredicates> rdbPredicates = nullptr;
NativeRdb::ConflictResolution conflictResolution = ConflictResolution::ON_CONFLICT_NONE;
int64_t updateRows = -1;
};
/*
* [JS API Prototype]
* [Promise]
* update(values: ValuesBucket, predicates: RdbPredicates, conflict?: ConflictResolution): Promise<number>;
*/
napi_value TransactionProxy::Update(napi_env env, napi_callback_info info)
{
auto context = std::make_shared<UpdateContext>();
auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) {
context->Parse(env, argc, argv, self);
};
auto exec = [context]() -> int {
CHECK_RETURN_ERR(context->transaction_ != nullptr && context->rdbPredicates != nullptr);
auto [code, updateRows] = context->StealTransaction()->Update(
context->valuesBucket, *context->rdbPredicates, context->conflictResolution);
context->updateRows = updateRows;
return code;
};
auto output = [context](napi_env env, napi_value &result) {
napi_status status = napi_create_int64(env, context->updateRows, &result);
CHECK_RETURN_SET_E(status == napi_ok, std::make_shared<InnerError>(E_ERROR));
};
context->SetAction(env, info, input, exec, output);
CHECK_RETURN_NULL(context->error == nullptr || context->error->GetCode() == OK);
return ASYNC_CALL(env, context);
}
struct InsertContext : public TransactionContext {
int32_t Parse(napi_env env, size_t argc, napi_value *argv, napi_value self)
{
ASSERT_RETURN_SET_ERROR(argc == 2 || argc == 3, std::make_shared<ParamNumError>("2 to 3"));
GetInstance(self);
ASSERT_RETURN_SET_ERROR(
transaction_ != nullptr, std::make_shared<ParamError>("transaction", "a transaction."));
CHECK_RETURN_ERR(JSUtils::Convert2Value(env, argv[0], tableName) == OK);
CHECK_RETURN_ERR(ParseValuesBucket(env, argv[1], valuesBucket) == OK);
// 'argv[2]' is an optional parameter
if (argc > 2 && !JSUtils::IsNull(env, argv[2])) {
// 'argv[2]' represents a ConflictResolution parameter
CHECK_RETURN_ERR(ParseConflictResolution(env, argv[2], conflictResolution));
}
return OK;
}
std::string tableName;
ValuesBucket valuesBucket;
NativeRdb::ConflictResolution conflictResolution = ConflictResolution::ON_CONFLICT_NONE;
int64_t insertRows = -1;
};
/*
* [JS API Prototype]
* [Promise]
* insert(table: string, values: ValuesBucket, conflict?: ConflictResolution): Promise<number>;
*/
napi_value TransactionProxy::Insert(napi_env env, napi_callback_info info)
{
auto context = std::make_shared<InsertContext>();
auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) {
context->Parse(env, argc, argv, self);
};
auto exec = [context]() -> int {
CHECK_RETURN_ERR(context->transaction_ != nullptr);
auto [code, insertRows] = context->StealTransaction()->Insert(
context->tableName, context->valuesBucket, context->conflictResolution);
context->insertRows = insertRows;
return code;
};
auto output = [context](napi_env env, napi_value &result) {
napi_status status = napi_create_int64(env, context->insertRows, &result);
CHECK_RETURN_SET_E(status == napi_ok, std::make_shared<InnerError>(E_ERROR));
};
context->SetAction(env, info, input, exec, output);
CHECK_RETURN_NULL(context->error == nullptr || context->error->GetCode() == OK);
return ASYNC_CALL(env, context);
}
struct BatchInsertContext : public TransactionContext {
int32_t Parse(napi_env env, size_t argc, napi_value *argv, napi_value self)
{
ASSERT_RETURN_SET_ERROR(argc == 2, std::make_shared<ParamNumError>("2"));
GetInstance(self);
ASSERT_RETURN_SET_ERROR(
transaction_ != nullptr, std::make_shared<ParamError>("transaction", "a transaction."));
ASSERT_RETURN_SET_ERROR(
JSUtils::Convert2Value(env, argv[0], tableName) == OK, std::make_shared<ParamError>("table", "a string."));
CHECK_RETURN_ERR(ParseValuesBuckets(env, argv[1], valuesBuckets) == OK);
return OK;
}
std::string tableName;
std::vector<ValuesBucket> valuesBuckets;
int64_t insertRows = -1;
};
/*
* [JS API Prototype]
* [Promise]
* batchInsert(table: string, values: Array<ValuesBucket>): Promise<number>;
*/
napi_value TransactionProxy::BatchInsert(napi_env env, napi_callback_info info)
{
auto context = std::make_shared<BatchInsertContext>();
auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) {
context->Parse(env, argc, argv, self);
};
auto exec = [context]() -> int {
CHECK_RETURN_ERR(context->transaction_ != nullptr);
auto [code, insertRows] = context->StealTransaction()->BatchInsert(context->tableName, context->valuesBuckets);
context->insertRows = insertRows;
return code;
};
auto output = [context](napi_env env, napi_value &result) {
napi_status status = napi_create_int64(env, context->insertRows, &result);
CHECK_RETURN_SET_E(status == napi_ok, std::make_shared<InnerError>(E_ERROR));
};
context->SetAction(env, info, input, exec, output);
CHECK_RETURN_NULL(context->error == nullptr || context->error->GetCode() == OK);
return ASYNC_CALL(env, context);
}
struct QueryContext : public TransactionContext {
int32_t Parse(napi_env env, size_t argc, napi_value *argv, napi_value self)
{
ASSERT_RETURN_SET_ERROR(argc == 1 || argc == 2, std::make_shared<ParamNumError>("1 to 2"));
GetInstance(self);
ASSERT_RETURN_SET_ERROR(
transaction_ != nullptr, std::make_shared<ParamError>("transaction", "a transaction."));
CHECK_RETURN_ERR(ParseRdbPredicatesProxy(env, argv[0], rdbPredicates) == OK);
if (argc > 1 && !JSUtils::IsNull(env, argv[1])) {
ASSERT_RETURN_SET_ERROR(JSUtils::Convert2Value(env, argv[1], columns) == OK,
std::make_shared<ParamError>("columns", "a Array<string>."));
}
return OK;
}
std::shared_ptr<RdbPredicates> rdbPredicates = nullptr;
std::vector<std::string> columns;
std::shared_ptr<ResultSet> resultSet;
};
/*
* [JS API Prototype]
* [Promise]
* query(predicates: RdbPredicates, columns?: Array<string>): Promise<ResultSet>;
*/
napi_value TransactionProxy::Query(napi_env env, napi_callback_info info)
{
auto context = std::make_shared<QueryContext>();
auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) {
context->Parse(env, argc, argv, self);
};
auto exec = [context]() -> int {
CHECK_RETURN_ERR(context->transaction_ != nullptr && context->rdbPredicates != nullptr);
context->resultSet = context->StealTransaction()->QueryByStep(*(context->rdbPredicates), context->columns);
return (context->resultSet != nullptr) ? E_OK : E_ALREADY_CLOSED;
};
auto output = [context](napi_env env, napi_value &result) {
result = ResultSetProxy::NewInstance(env, context->resultSet);
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 ASYNC_CALL(env, context);
}
struct QuerySqlContext : public TransactionContext {
int32_t Parse(napi_env env, size_t argc, napi_value *argv, napi_value self)
{
ASSERT_RETURN_SET_ERROR(argc == 1 || argc == 2, std::make_shared<ParamNumError>("1 to 2"));
GetInstance(self);
ASSERT_RETURN_SET_ERROR(
transaction_ != nullptr, std::make_shared<ParamError>("transaction", "a transaction."));
ASSERT_RETURN_SET_ERROR(
JSUtils::Convert2Value(env, argv[0], sql) == OK, std::make_shared<ParamError>("sql", "a string."));
if (argc > 1 && !JSUtils::IsNull(env, argv[1])) {
ASSERT_RETURN_SET_ERROR(JSUtils::Convert2Value(env, argv[1], bindArgs) == OK,
std::make_shared<ParamError>("bindArgs", "a Array<ValueType>."));
}
return OK;
}
std::string sql;
std::vector<ValueObject> bindArgs;
std::shared_ptr<ResultSet> resultSet;
};
/*
* [JS API Prototype]
* [Promise]
* querySql(sql: string, bindArgs?: Array<ValueType>): Promise<ResultSet>;
*/
napi_value TransactionProxy::QuerySql(napi_env env, napi_callback_info info)
{
auto context = std::make_shared<QuerySqlContext>();
auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) {
context->Parse(env, argc, argv, self);
};
auto exec = [context]() -> int {
CHECK_RETURN_ERR(context->transaction_ != nullptr);
context->resultSet = context->StealTransaction()->QueryByStep(context->sql, context->bindArgs);
return (context->resultSet != nullptr) ? E_OK : E_ALREADY_CLOSED;
};
auto output = [context](napi_env env, napi_value &result) {
result = ResultSetProxy::NewInstance(env, context->resultSet);
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 ASYNC_CALL(env, context);
}
struct ExecuteContext : public TransactionContext {
int32_t Parse(napi_env env, size_t argc, napi_value *argv, napi_value self)
{
ASSERT_RETURN_SET_ERROR(argc == 1 || argc == 2, std::make_shared<ParamNumError>("1 to 2"));
GetInstance(self);
ASSERT_RETURN_SET_ERROR(transaction_ != nullptr, std::make_shared<ParamError>("transaction", "a transaction."));
CHECK_RETURN_ERR(JSUtils::Convert2Value(env, argv[0], sql) == OK);
if (argc > 1 && !JSUtils::IsNull(env, argv[1])) {
CHECK_RETURN_ERR(JSUtils::Convert2Value(env, argv[1], bindArgs) == OK);
}
return OK;
}
std::string sql;
std::vector<ValueObject> bindArgs;
ValueObject output;
};
/*
* [JS API Prototype]
* [Promise]
* execute(sql: string, args?: Array<ValueType>): Promise<ValueType>;
*/
napi_value TransactionProxy::Execute(napi_env env, napi_callback_info info)
{
auto context = std::make_shared<ExecuteContext>();
auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) {
context->Parse(env, argc, argv, self);
};
auto exec = [context]() -> int {
CHECK_RETURN_ERR(context->transaction_ != nullptr);
auto status = E_ERROR;
std::tie(status, context->output) = context->StealTransaction()->Execute(context->sql, context->bindArgs);
return status;
};
auto output = [context](napi_env env, napi_value &result) {
result = JSUtils::Convert2JSValue(env, context->output);
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 ASYNC_CALL(env, context);
}
} // namespace OHOS::RelationalStoreJsKit

View File

@ -42,7 +42,7 @@ public:
~ConnectionPool();
static std::pair<RebuiltType, std::shared_ptr<ConnectionPool>> HandleDataCorruption
(const RdbStoreConfig &storeConfig, int &errCode);
std::pair<int32_t, std::shared_ptr<Connection>> CreateConnection(bool isReadOnly);
std::pair<int32_t, std::shared_ptr<Connection>> CreateTransConn(bool limited = true);
SharedConn AcquireConnection(bool isReadOnly);
SharedConn Acquire(bool isReadOnly, std::chrono::milliseconds ms = INVALID_TIME);
// this interface is only provided for resultSet
@ -50,6 +50,8 @@ public:
std::pair<SharedConn, SharedConns> AcquireAll(int32_t time);
std::pair<int32_t, SharedConn> DisableWal();
int32_t EnableWal();
int32_t Dump(bool isWriter, const char *header);
int RestartReaders();
int ConfigLocale(const std::string &localeStr);
int ChangeDbFileForRestore(const std::string &newPath, const std::string &backupPath,
@ -76,16 +78,18 @@ private:
std::shared_ptr<Connection> GetConnect();
int64_t GetUsingTime() const;
bool IsWriter() const;
int32_t Unused(bool inTrans);
int32_t Unused(int32_t count);
};
struct Container {
using Creator = std::function<std::pair<int32_t, std::shared_ptr<Connection>>()>;
static constexpr int32_t MAX_RIGHT = 0x4FFFFFFF;
static constexpr int32_t MIN_TRANS_ID = 10000;
bool disable_ = true;
int max_ = 0;
int total_ = 0;
int count_ = 0;
int trans_ = 0;
int32_t left_ = 0;
int32_t right_ = 0;
std::chrono::seconds timeout_;
@ -99,13 +103,15 @@ private:
int32_t ConfigLocale(const std::string &locale);
std::shared_ptr<ConnNode> Acquire(std::chrono::milliseconds milliS);
std::list<std::shared_ptr<ConnNode>> AcquireAll(std::chrono::milliseconds milliS);
std::pair<int32_t, std::shared_ptr<ConnNode>> Create();
void Disable();
void Enable();
int32_t Release(std::shared_ptr<ConnNode> node);
int32_t Drop(std::shared_ptr<ConnNode> node);
int32_t Clear();
bool IsFull();
int32_t Dump(const char *header, bool inTrans);
int32_t Dump(const char *header, int32_t count);
private:
int32_t ExtendNode();
@ -115,8 +121,8 @@ private:
explicit ConnectionPool(const RdbStoreConfig &storeConfig);
std::pair<int32_t, std::shared_ptr<Connection>> Init(bool isAttach = false, bool needWriter = false);
int32_t GetMaxReaders(const RdbStoreConfig &config);
std::shared_ptr<Connection> Convert2AutoConn(std::shared_ptr<ConnNode> node);
void ReleaseNode(std::shared_ptr<ConnNode> node);
std::shared_ptr<Connection> Convert2AutoConn(std::shared_ptr<ConnNode> node, bool isTrans = false);
void ReleaseNode(std::shared_ptr<ConnNode> node, bool reuse = true);
int RestoreByDbSqliteType(const std::string &newPath, const std::string &backupPath, SlaveStatus &slaveStatus);
int RestoreMasterDb(const std::string &newPath, const std::string &backupPath);
bool CheckIntegrity(const std::string &dbPath);
@ -124,6 +130,7 @@ private:
static constexpr int LIMITATION = 1024;
static constexpr uint32_t ITER_V1 = 5000;
static constexpr uint32_t ITERS_COUNT = 2;
static constexpr uint32_t MAX_TRANS = 4;
const RdbStoreConfig &config_;
RdbStoreConfig attachConfig_;
Container writers_;
@ -136,6 +143,7 @@ private:
std::mutex transMutex_;
bool transactionUsed_;
std::atomic<bool> isInTransaction_ = false;
std::atomic<uint32_t> transCount_ = 0;
};
} // namespace NativeRdb

View File

@ -73,6 +73,7 @@ public:
KeyFiles(const std::string &dbPath, bool openFile = true);
~KeyFiles();
const std::string &GetKeyFile(KeyFileType type);
int32_t InitKeyPath();
int32_t DestroyLock();
int32_t Lock();
int32_t Unlock();

View File

@ -44,8 +44,8 @@ namespace OHOS::NativeRdb {
class DelayNotify;
class RdbStoreLocalObserver {
public:
explicit RdbStoreLocalObserver(DistributedRdb::RdbStoreObserver *observer) : observer_(observer) {};
virtual ~RdbStoreLocalObserver() {};
explicit RdbStoreLocalObserver(DistributedRdb::RdbStoreObserver *observer) : observer_(observer){};
virtual ~RdbStoreLocalObserver(){};
void OnChange()
{
observer_->OnChange();
@ -54,14 +54,15 @@ public:
{
return observer_;
}
private:
DistributedRdb::RdbStoreObserver *observer_ = nullptr;
};
class RdbStoreLocalSharedObserver : public AAFwk::DataAbilityObserverStub {
public:
explicit RdbStoreLocalSharedObserver(DistributedRdb::RdbStoreObserver *observer) : observer_(observer) {};
virtual ~RdbStoreLocalSharedObserver() {};
explicit RdbStoreLocalSharedObserver(DistributedRdb::RdbStoreObserver *observer) : observer_(observer){};
virtual ~RdbStoreLocalSharedObserver(){};
void OnChange() override
{
observer_->OnChange();
@ -70,6 +71,7 @@ public:
{
return observer_;
}
private:
DistributedRdb::RdbStoreObserver *observer_ = nullptr;
};
@ -79,46 +81,23 @@ public:
RdbStoreImpl(const RdbStoreConfig &config);
RdbStoreImpl(const RdbStoreConfig &config, int &errCode);
~RdbStoreImpl() override;
const RdbStoreConfig &GetConfig();
int Insert(int64_t &outRowId, const std::string &table, const ValuesBucket &values) override;
int BatchInsert(int64_t& outInsertNum, const std::string& table, const std::vector<ValuesBucket>& values) override;
std::pair<int, int64_t> Insert(const std::string &table, const Row &row, Resolution resolution) override;
std::pair<int, int64_t> BatchInsert(const std::string& table, const ValuesBuckets& values) override;
int Replace(int64_t &outRowId, const std::string &table, const ValuesBucket &initialValues) override;
int InsertWithConflictResolution(int64_t &outRowId, const std::string &table, const ValuesBucket &values,
ConflictResolution conflictResolution) override;
int Update(int &changedRows, const std::string &table, const ValuesBucket &values, const std::string &whereClause,
const std::vector<std::string> &whereArgs) override;
int Update(int &changedRows, const std::string &table, const ValuesBucket &values, const std::string &whereClause,
const std::vector<ValueObject> &bindArgs) override;
int UpdateWithConflictResolution(int &changedRows, const std::string &table, const ValuesBucket &values,
const std::string &whereClause, const std::vector<std::string> &whereArgs,
ConflictResolution conflictResolution) override;
int UpdateWithConflictResolution(int &changedRows, const std::string &table, const ValuesBucket &values,
const std::string &whereClause, const std::vector<ValueObject> &bindArgs,
ConflictResolution conflictResolution) override;
int Delete(int &deletedRows, const std::string &table, const std::string &whereClause,
const std::vector<std::string> &whereArgs) override;
int Delete(int &deletedRows, const std::string &table, const std::string &whereClause,
const std::vector<ValueObject> &bindArgs) override;
std::shared_ptr<AbsSharedResultSet> Query(int &errCode, bool distinct,
const std::string &table, const std::vector<std::string> &columns,
const std::string &whereClause, const std::vector<ValueObject> &bindArgs, const std::string &groupBy,
const std::string &indexName, const std::string &orderBy, const int &limit, const int &offset) override;
std::shared_ptr<AbsSharedResultSet> QuerySql(const std::string &sql,
const std::vector<std::string> &sqlArgs) override;
std::shared_ptr<AbsSharedResultSet> QuerySql(const std::string &sql,
const std::vector<ValueObject> &bindArgs) override;
int ExecuteSql(const std::string& sql, const std::vector<ValueObject>& bindArgs) override;
std::pair<int32_t, ValueObject> Execute(const std::string& sql, const std::vector<ValueObject>& bindArgs,
int64_t trxId) override;
int ExecuteAndGetLong(int64_t &outValue, const std::string &sql, const std::vector<ValueObject> &bindArgs) override;
int ExecuteAndGetString(std::string &outValue, const std::string &sql,
const std::vector<ValueObject> &bindArgs) override;
int ExecuteForLastInsertedRowId(int64_t &outValue, const std::string &sql,
const std::vector<ValueObject> &bindArgs) override;
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;
std::pair<int, int> Update(const std::string &table, const Row &row, const std::string &where, const Values &args,
Resolution resolution) override;
int Delete(int &deletedRows, const std::string &table, const std::string &whereClause, const Values &args) override;
std::shared_ptr<AbsSharedResultSet> QuerySql(const std::string &sql, const Values &args) override;
std::shared_ptr<ResultSet> QueryByStep(const std::string &sql, const Values &args) override;
std::shared_ptr<ResultSet> RemoteQuery(const std::string &device, const AbsRdbPredicates &predicates,
const Fields &columns, int &errCode) override;
std::pair<int32_t, std::shared_ptr<ResultSet>> QuerySharingResource(const AbsRdbPredicates &predicates,
const Fields &columns) override;
int ExecuteSql(const std::string &sql, const Values &args) override;
std::pair<int32_t, ValueObject> Execute(const std::string &sql, const Values &args, int64_t trxId) override;
int ExecuteAndGetLong(int64_t &outValue, const std::string &sql, const Values &args) override;
int ExecuteAndGetString(std::string &outValue, const std::string &sql, const Values &args) override;
int ExecuteForLastInsertedRowId(int64_t &outValue, const std::string &sql, const Values &args) override;
int ExecuteForChangedRowCount(int64_t &outValue, const std::string &sql, const Values &args) override;
int GetVersion(int &version) override;
int SetVersion(int version) override;
int BeginTransaction() override;
@ -134,68 +113,47 @@ public:
bool IsMemoryRdb() const override;
bool IsHoldingConnection() override;
bool IsSlaveDiffFromMaster() const override;
int ConfigLocale(const std::string &localeStr);
int Backup(const std::string &databasePath, const std::vector<uint8_t> &encryptKey) override;
int Restore(const std::string &backupPath, const std::vector<uint8_t> &newKey) override;
std::string GetName();
std::string GetFileType();
std::shared_ptr<ResultSet> QueryByStep(const std::string& sql, const std::vector<std::string>& sqlArgs) override;
std::shared_ptr<ResultSet> QueryByStep(const std::string &sql, const std::vector<ValueObject> &args) override;
std::shared_ptr<ResultSet> QueryByStep(
const AbsRdbPredicates &predicates, const std::vector<std::string> &columns) override;
std::shared_ptr<AbsSharedResultSet> Query(
const AbsRdbPredicates &predicates, const std::vector<std::string> &columns) override;
std::pair<int32_t, std::shared_ptr<ResultSet>> QuerySharingResource(
const AbsRdbPredicates &predicates, const std::vector<std::string> &columns) override;
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::shared_ptr<ResultSet> RemoteQuery(const std::string &device, const AbsRdbPredicates &predicates,
const std::vector<std::string> &columns, int &errCode) override;
int SetDistributedTables(const std::vector<std::string> &tables, int32_t type,
const DistributedRdb::DistributedConfig &distributedConfig) override;
std::string ObtainDistributedTableName(const std::string& device, const std::string& table, int &errCode) override;
std::string ObtainDistributedTableName(const std::string &device, const std::string &table, int &errCode) override;
int Sync(const SyncOption &option, const AbsRdbPredicates &predicate, const AsyncBrief &async) override;
int Sync(const SyncOption &option, const std::vector<std::string> &tables, const AsyncDetail &async) override;
int Sync(const SyncOption &option, const AbsRdbPredicates &predicate, const AsyncDetail &async) override;
int Subscribe(const SubscribeOption& option, RdbStoreObserver *observer) override;
int UnSubscribe(const SubscribeOption& option, RdbStoreObserver *observer) override;
int SubscribeObserver(const SubscribeOption& option, const std::shared_ptr<RdbStoreObserver> &observer) override;
int UnsubscribeObserver(const SubscribeOption& option, const std::shared_ptr<RdbStoreObserver> &observer) override;
int Subscribe(const SubscribeOption &option, RdbStoreObserver *observer) override;
int UnSubscribe(const SubscribeOption &option, RdbStoreObserver *observer) override;
int SubscribeObserver(const SubscribeOption &option, const std::shared_ptr<RdbStoreObserver> &observer) override;
int UnsubscribeObserver(const SubscribeOption &option, const std::shared_ptr<RdbStoreObserver> &observer) override;
int RegisterAutoSyncCallback(std::shared_ptr<DetailProgressObserver> observer) override;
int UnregisterAutoSyncCallback(std::shared_ptr<DetailProgressObserver> observer) override;
int Notify(const std::string &event) override;
int SetSearchable(bool isSearchable) override;
ModifyTime GetModifyTime(const std::string& table, const std::string& columnName,
std::vector<PRIKey>& keys) override;
ModifyTime GetModifyTime(const std::string &table, const std::string &columnName,
std::vector<PRIKey> &keys) override;
int GetRebuilt(RebuiltType &rebuilt) 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;
void AfterOpen(const RdbStoreConfig &config);
std::pair<int32_t, int32_t> Attach(const RdbStoreConfig &config, const std::string &attachName,
int32_t waitTime) override;
std::pair<int32_t, int32_t> Detach(const std::string &attachName, int32_t waitTime) override;
int ModifyLockStatus(const AbsRdbPredicates &predicates, bool isLock) override;
int32_t GetDbType() const override;
int32_t ExchangeSlaverToMaster();
std::pair<int32_t, uint32_t> LockCloudContainer() override;
int32_t UnlockCloudContainer() override;
int InterruptBackup() override;
int32_t GetBackupStatus() const override;
std::pair<int32_t, std::shared_ptr<Transaction>> CreateTransaction(int32_t type) override;
// not virtual functions /
const RdbStoreConfig &GetConfig();
int ConfigLocale(const std::string &localeStr);
std::string GetName();
std::string GetFileType();
int32_t ExchangeSlaverToMaster();
protected:
std::string GetLogTableName(const std::string &tableName) override;
private:
using Stmt = std::shared_ptr<Statement>;
@ -210,48 +168,37 @@ private:
const std::string &sql, const ValueObject &object, int sqlType);
int CheckAttach(const std::string &sql);
std::pair<int32_t, Stmt> BeginExecuteSql(const std::string &sql);
auto GenerateSql(const std::string& table, const std::vector<ValuesBucket>& buckets, int limit);
auto GenerateSql(const std::string& table, const ValuesBuckets& buckets, int limit);
int GetDataBasePath(const std::string &databasePath, std::string &backupFilePath);
int ExecuteSqlInner(const std::string &sql, const std::vector<ValueObject> &bindArgs);
void SetAssetStatus(const ValueObject &val, int32_t status);
void DoCloudSync(const std::string &table);
int InnerSync(const DistributedRdb::RdbService::Option &option, const DistributedRdb::PredicatesMemo &predicates,
const AsyncDetail &async);
int InnerBackup(const std::string& databasePath,
const std::vector<uint8_t>& destEncryptKey = std::vector<uint8_t>());
ModifyTime GetModifyTimeByRowId(const std::string& logTable, std::vector<PRIKey>& keys);
int InnerBackup(const std::string &databasePath,
const std::vector<uint8_t> &destEncryptKey = std::vector<uint8_t>());
ModifyTime GetModifyTimeByRowId(const std::string &logTable, std::vector<PRIKey> &keys);
Uri GetUri(const std::string &event);
int SubscribeLocal(const SubscribeOption& option, RdbStoreObserver *observer);
int SubscribeLocalShared(const SubscribeOption& option, RdbStoreObserver *observer);
int32_t SubscribeLocalDetail(const SubscribeOption& option, const std::shared_ptr<RdbStoreObserver> &observer);
int SubscribeRemote(const SubscribeOption& option, RdbStoreObserver *observer);
int UnSubscribeLocal(const SubscribeOption& option, RdbStoreObserver *observer);
int UnSubscribeLocalAll(const SubscribeOption& option);
int UnSubscribeLocalShared(const SubscribeOption& option, RdbStoreObserver *observer);
int UnSubscribeLocalSharedAll(const SubscribeOption& option);
int32_t UnsubscribeLocalDetail(const SubscribeOption& option, const std::shared_ptr<RdbStoreObserver> &observer);
int UnSubscribeRemote(const SubscribeOption& option, RdbStoreObserver *observer);
int SubscribeLocal(const SubscribeOption &option, RdbStoreObserver *observer);
int SubscribeLocalShared(const SubscribeOption &option, RdbStoreObserver *observer);
int32_t SubscribeLocalDetail(const SubscribeOption &option, const std::shared_ptr<RdbStoreObserver> &observer);
int SubscribeRemote(const SubscribeOption &option, RdbStoreObserver *observer);
int UnSubscribeLocal(const SubscribeOption &option, RdbStoreObserver *observer);
int UnSubscribeLocalAll(const SubscribeOption &option);
int UnSubscribeLocalShared(const SubscribeOption &option, RdbStoreObserver *observer);
int UnSubscribeLocalSharedAll(const SubscribeOption &option);
int32_t UnsubscribeLocalDetail(const SubscribeOption &option, const std::shared_ptr<RdbStoreObserver> &observer);
int UnSubscribeRemote(const SubscribeOption &option, RdbStoreObserver *observer);
int RegisterDataChangeCallback();
void InitDelayNotifier();
bool ColHasSpecificField(const std::vector<std::string> &columns);
std::pair<int32_t, Stmt> CreateWriteableStmt(const std::string &sql);
std::pair<int32_t, Stmt> GetStatement(const std::string& sql, std::shared_ptr<Connection> conn) const;
std::pair<int32_t, Stmt> GetStatement(const std::string& sql, bool read = false) const;
int AttachInner(const std::string &attachName,
const std::string &dbPath, const std::vector<uint8_t> &key, int32_t waitTime);
std::string GetSecManagerName(const RdbStoreConfig &config);
std::pair<int32_t, std::shared_ptr<Connection>> CreateWritableConn();
std::vector<ValueObject> CreateBackupBindArgs(const std::string &databasePath,
const std::vector<uint8_t> &destEncryptKey);
std::pair<int32_t, Stmt> GetStatement(const std::string &sql, std::shared_ptr<Connection> conn) const;
std::pair<int32_t, Stmt> GetStatement(const std::string &sql, bool read = false) const;
int AttachInner(const RdbStoreConfig &config, const std::string &attachName, const std::string &dbPath,
const std::vector<uint8_t> &key, int32_t waitTime);
int SetDefaultEncryptSql(const std::shared_ptr<Statement> &statement, std::string sql,
const RdbStoreConfig &config);
int SetDefaultEncryptAlgo(const ConnectionPool::SharedConn &conn, const RdbStoreConfig &config);
int GetHashKeyForLockRow(const AbsRdbPredicates &predicates, std::vector<std::vector<uint8_t>> &hashKeys);
int InsertWithConflictResolutionEntry(int64_t &outRowId, const std::string &table, const ValuesBucket &values,
ConflictResolution conflictResolution);
int UpdateWithConflictResolutionEntry(int &changedRows, const std::string &table, const ValuesBucket &values,
const std::string &whereClause, const std::vector<ValueObject> &bindArgs,
ConflictResolution conflictResolution);
template<typename T>
int BatchInsertEntry(const std::string& table, const T& values, size_t rowSize, int64_t& outInsertNum);
int ExecuteSqlEntry(const std::string& sql, const std::vector<ValueObject>& bindArgs);
std::pair<int32_t, ValueObject> ExecuteEntry(const std::string& sql, const std::vector<ValueObject>& bindArgs,
int64_t trxId);
int GetSlaveName(const std::string &dbName, std::string &backupFilePath);
void NotifyDataChange();
bool TryGetMasterSlaveBackupPath(const std::string &srcPath, std::string &destPath, bool isRestore = false);
@ -286,9 +233,7 @@ private:
std::map<std::string, std::list<sptr<RdbStoreLocalSharedObserver>>> localSharedObservers_;
ConcurrentMap<std::string, std::string> attachedInfo_;
ConcurrentMap<int64_t, std::shared_ptr<Connection>> trxConnMap_ = {};
static inline ValueObject emptyValueObject_;
static inline std::reference_wrapper<ValueObject> emptyValueObjectRef_ = emptyValueObject_;
std::list<std::weak_ptr<Transaction>> transactions_;
};
} // namespace OHOS::NativeRdb
#endif

View File

@ -25,10 +25,10 @@
#include "lru_bucket.h"
#include "rdb_open_callback.h"
#include "rdb_store_config.h"
#include "rdb_store_impl.h"
namespace OHOS {
namespace NativeRdb {
class RdbStoreImpl;
class RdbStoreManager {
public:
static RdbStoreManager &GetInstance();
@ -49,8 +49,8 @@ private:
bool IsConfigInvalidChanged(const std::string &path, RdbStoreConfig &config);
int32_t GetParamFromService(DistributedRdb::RdbSyncerParam &param);
static Param GetSyncParam(const RdbStoreConfig &config);
std::shared_ptr<RdbStoreImpl> GetStoreFromCache(const RdbStoreConfig &config, const std::string &path);
static std::map<std::string, Info> Collector(const RdbStoreConfig &config);
std::shared_ptr<RdbStoreImpl> GetStoreFromCache(const RdbStoreConfig &config, const std::string &path);
static constexpr uint32_t BUCKET_MAX_SIZE = 4;
static const bool regCollector_;

View File

@ -28,7 +28,6 @@
#include "rdb_store_config.h"
#include "sqlite3sym.h"
#include "sqlite_statement.h"
#include "task_executor.h"
#include "value_object.h"
typedef struct ClientChangedData ClientChangedData;
@ -134,13 +133,15 @@ private:
static constexpr int DEFAULT_BUSY_TIMEOUT_MS = 2000;
static constexpr int BACKUP_PAGES_PRE_STEP = 12800; // 1024 * 4 * 12800 == 50m
static constexpr int BACKUP_PRE_WAIT_TIME = 10;
static constexpr ssize_t SLAVE_WAL_SIZE_LIMIT = 2147483647; // 2147483647 = 2g - 1
static constexpr uint32_t NO_ITER = 0;
static constexpr uint32_t WAL_INDEX = 2;
static const int32_t regCreator_;
static const int32_t regRepairer_;
static const int32_t regDeleter_;
static const int32_t regCollector_;
std::atomic<TaskExecutor::TaskId> backupId_ = TaskExecutor::INVALID_TASK_ID;
std::atomic<uint64_t> backupId_;
sqlite3 *dbHandle_;
bool isWriter_;
bool isReadOnly_;

View File

@ -22,11 +22,11 @@
#include <string>
#include <thread>
#include <vector>
#include <chrono>
#include "abs_shared_result_set.h"
#include "connection.h"
#include "shared_block.h"
#include "connection_pool.h"
#include "statement.h"
#include "value_object.h"
@ -34,8 +34,10 @@ namespace OHOS {
namespace NativeRdb {
class SqliteSharedResultSet : public AbsSharedResultSet {
public:
SqliteSharedResultSet(std::shared_ptr<ConnectionPool> pool, std::string path,
std::string sql, const std::vector<ValueObject> &bindArgs);
using Values = std::vector<ValueObject>;
using Conn = std::shared_ptr<Connection>;
using Time = std::chrono::steady_clock::time_point;
SqliteSharedResultSet(Time start, Conn conn, std::string sql, const Values &args, const std::string &path);
~SqliteSharedResultSet() override;
int Close() override;
int32_t OnGo(int oldPosition, int newPosition) override;
@ -72,7 +74,6 @@ private:
std::shared_ptr<Statement> statement_;
std::string qrySql_;
std::vector<ValueObject> bindArgs_;
std::vector<std::string> columnNames_;
std::mutex mutex_;
};
} // namespace NativeRdb

View File

@ -26,6 +26,8 @@ namespace OHOS {
namespace NativeRdb {
class SqliteSqlBuilder {
public:
using RefValue = std::reference_wrapper<ValueObject>;
using BatchRefSqls = std::vector<std::pair<std::string, std::vector<std::vector<RefValue>>>>;
SqliteSqlBuilder();
~SqliteSqlBuilder();
static std::string BuildDeleteString(const std::string &tableName, const std::string &index,
@ -53,18 +55,21 @@ public:
const AbsRdbPredicates &predicates, const std::vector<std::string> &columns, const std::string &logTable);
static std::string GetSqlArgs(size_t size);
template<typename T>
using ExecuteSqlsType = std::vector<std::pair<std::string, std::vector<std::vector<T>>>>;
template<typename T>
static ExecuteSqlsType<T> MakeExecuteSqls(const std::string &sql, const std::vector<T> &args, int fieldSize,
int limit);
static BatchRefSqls GenerateSqls(const std::string &table, const ValuesBuckets &buckets, int limit);
static void UpdateAssetStatus(const ValueObject &value, int32_t status);
private:
static BatchRefSqls MakeExecuteSqls(const std::string &sql, const std::vector<RefValue> &args, int fieldSize,
int limit);
static void AppendClause(std::string &builder, const std::string &name,
const std::string &clause, const std::string &table = "");
static void AppendColumns(
std::string &builder, const std::vector<std::string> &columns, const std::string &table = "");
static constexpr const char *SHARING_RESOURCE = "sharing_resource";
static constexpr uint32_t EXPANSION = 2;
static ValueObject nullObject_;
static std::reference_wrapper<ValueObject> nullRef_;
static std::string HandleTable(const std::string &tableName);
};
} // namespace NativeRdb
} // namespace OHOS

View File

@ -30,8 +30,10 @@ namespace OHOS {
namespace NativeRdb {
class StepResultSet : public AbsResultSet {
public:
StepResultSet(std::shared_ptr<ConnectionPool> pool, const std::string &sql,
const std::vector<ValueObject> &selectionArgs);
using Values = std::vector<ValueObject>;
using Conn = std::shared_ptr<Connection>;
using Time = std::chrono::steady_clock::time_point;
StepResultSet(Time start, Conn conn, const std::string &sql, const Values &args, bool safe = false);
~StepResultSet() override;
int GetColumnType(int columnIndex, ColumnType &columnType) override;
int GoToRow(int position) override;
@ -60,12 +62,11 @@ private:
static const int EMPTY_ROW_COUNT = 0;
bool isSupportCountRow_ = true;
std::shared_ptr<Statement> sqliteStatement_;
std::shared_ptr<Statement> statement_;
std::shared_ptr<Connection> conn_;
std::string sql_;
std::vector<ValueObject> args_;
mutable std::shared_mutex mutex_;
};
} // namespace NativeRdb
} // namespace OHOS

View File

@ -0,0 +1,48 @@
/*
* Copyright (c) 2024 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef NATIVE_RDB_TRANS_DB_H
#define NATIVE_RDB_TRANS_DB_H
#include <memory>
#include "connection.h"
#include "rdb_store.h"
#include "statement.h"
namespace OHOS::NativeRdb {
class TransDB : public RdbStore {
public:
TransDB(std::shared_ptr<Connection> conn, const std::string &name);
std::pair<int, int64_t> Insert(const std::string &table, const Row &row, Resolution resolution) override;
std::pair<int, int64_t> BatchInsert(const std::string &table, const RefRows &rows) override;
std::pair<int, int> Update(const std::string &table, const Row &row, const std::string &where, const Values &args,
Resolution resolution) override;
int Delete(int &deletedRows, const std::string &table, const std::string &whereClause, const Values &args) override;
std::shared_ptr<AbsSharedResultSet> QuerySql(const std::string &sql, const Values &args) override;
std::shared_ptr<ResultSet> QueryByStep(const std::string &sql, const Values &args) override;
std::pair<int32_t, ValueObject> Execute(const std::string &sql, const Values &args, int64_t trxId) override;
int GetVersion(int &version) override;
int SetVersion(int version) override;
int Sync(const SyncOption &option, const std::vector<std::string> &tables, const AsyncDetail &async) override;
private:
std::pair<int32_t, std::shared_ptr<Statement>> GetStatement(const std::string &sql) const;
int32_t maxArgs_ = 0;
int64_t vSchema_ = 0;
std::weak_ptr<Connection> conn_;
std::string name_;
};
} // namespace OHOS::NativeRdb
#endif // NATIVE_RDB_TRANS_DB_H

View File

@ -0,0 +1,72 @@
/*
* Copyright (c) 2024 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef NATIVE_RDB_TRANSACTION_IMPL_H
#define NATIVE_RDB_TRANSACTION_IMPL_H
#include <mutex>
#include <memory>
#include <vector>
#include "connection.h"
#include "transaction.h"
namespace OHOS::NativeRdb {
class RdbStore;
class TransactionImpl : public Transaction {
public:
TransactionImpl(std::shared_ptr<Connection> connection, const std::string &name);
~TransactionImpl() override;
int32_t Commit() override;
int32_t Rollback() override;
int32_t Close() override;
std::pair<int32_t, int64_t> Insert(const std::string &table, const Row &row, Resolution resolution) override;
std::pair<int32_t, int64_t> BatchInsert(const std::string &table, const Rows &rows) override;
std::pair<int32_t, int64_t> BatchInsert(const std::string &table, const RefRows &rows) override;
std::pair<int, int> Update(const std::string &table, const Row &row, const std::string &where,
const Values &args, Resolution resolution) override;
std::pair<int32_t, int32_t> Update(const Row &row, const AbsRdbPredicates &predicates,
Resolution resolution) override;
std::pair<int32_t, int32_t> Delete(const std::string &table, const std::string &whereClause,
const Values &args) override;
std::pair<int32_t, int32_t> Delete(const AbsRdbPredicates &predicates) override;
std::shared_ptr<ResultSet> QueryByStep(const std::string &sql, const Values &args) override;
std::shared_ptr<ResultSet> QueryByStep(const AbsRdbPredicates &predicates, const Fields &columns) override;
std::pair<int32_t, ValueObject> Execute(const std::string &sql, const Values &args) override;
static std::pair<int32_t, std::shared_ptr<Transaction>> Create(
int32_t type, std::shared_ptr<Connection> connection, const std::string &name);
private:
static std::string GetBeginSql(int32_t type);
int32_t Begin(int32_t type);
int32_t CloseInner();
std::shared_ptr<RdbStore> GetStore();
void AddResultSet(std::weak_ptr<ResultSet> resultSet);
std::string name_;
std::recursive_mutex mutex_;
std::shared_ptr<RdbStore> store_;
std::shared_ptr<Connection> connection_;
std::vector<std::weak_ptr<ResultSet>> resultSets_;
static const int32_t regCreator_;
static constexpr char COMMIT_SQL[] = "COMMIT;";
static constexpr char ROLLBACK_SQL[] = "ROLLBACK;";
static constexpr const char *BEGIN_SQLS[] = { "BEGIN DEFERRED;", "BEGIN IMMEDIATE;", "BEGIN EXCLUSIVE;" };
};
}
#endif

View File

@ -1,80 +0,0 @@
/*
* Copyright (c) 2024 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef OHOS_DISTRIBUTED_DATA_RELATIONAL_STORE_FRAMEWORKS_NATIVE_RDB_INCLUDE_CONNECTION_H
#define OHOS_DISTRIBUTED_DATA_RELATIONAL_STORE_FRAMEWORKS_NATIVE_RDB_INCLUDE_CONNECTION_H
#include <cstdint>
#include <functional>
#include <memory>
#include <set>
#include <string>
#include <utility>
#include "rdb_common.h"
#include "rdb_types.h"
#include "statement.h"
namespace OHOS::NativeRdb {
class RdbStoreConfig;
class Statement;
class Connection {
public:
using Info = DistributedRdb::RdbDebugInfo;
using SConn = std::shared_ptr<Connection>;
using Stmt = std::shared_ptr<Statement>;
using Notifier = std::function<void(const std::set<std::string> &tables)>;
using Creator = std::pair<int32_t, SConn> (*)(const RdbStoreConfig &config, bool isWriter);
using Repairer = int32_t (*)(const RdbStoreConfig &config);
using Deleter = int32_t (*)(const RdbStoreConfig &config);
using Collector = std::map<std::string, Info> (*)(const RdbStoreConfig &config);
static std::pair<int32_t, SConn> Create(const RdbStoreConfig &config, bool isWriter);
static int32_t Repair(const RdbStoreConfig &config);
static int32_t Delete(const RdbStoreConfig &config);
static std::map<std::string, Info> Collect(const RdbStoreConfig &config);
static int32_t RegisterCreator(int32_t dbType, Creator creator);
static int32_t RegisterRepairer(int32_t dbType, Repairer repairer);
static int32_t RegisterDeleter(int32_t dbType, Deleter deleter);
static int32_t RegisterCollector(int32_t dbType, Collector collector);
int32_t SetId(int32_t id);
int32_t GetId() const;
virtual ~Connection() = default;
virtual int32_t OnInitialize() = 0;
virtual std::pair<int32_t, Stmt> CreateStatement(const std::string &sql, SConn conn) = 0;
virtual int32_t GetDBType() const = 0;
virtual bool IsWriter() const = 0;
virtual int32_t ReSetKey(const RdbStoreConfig &config) = 0;
virtual int32_t TryCheckPoint(bool timeout) = 0;
virtual int32_t LimitWalSize() = 0;
virtual int32_t ConfigLocale(const std::string &localeStr) = 0;
virtual int32_t CleanDirtyData(const std::string &table, uint64_t cursor) = 0;
virtual int32_t SubscribeTableChanges(const Notifier &notifier) = 0;
virtual int32_t GetMaxVariable() const = 0;
virtual int32_t GetJournalMode() = 0;
virtual int32_t ClearCache() = 0;
virtual int32_t Subscribe(const std::string &event,
const std::shared_ptr<DistributedRdb::RdbStoreObserver> &observer) = 0;
virtual int32_t Unsubscribe(const std::string &event,
const std::shared_ptr<DistributedRdb::RdbStoreObserver> &observer) = 0;
virtual int32_t Backup(const std::string &databasePath, const std::vector<uint8_t> &destEncryptKey,
bool isAsync, SlaveStatus &slaveStatus) = 0;
virtual int32_t Restore(const std::string &databasePath, const std::vector<uint8_t> &destEncryptKey,
SlaveStatus &slaveStatus) = 0;
virtual ExchangeStrategy GenerateExchangeStrategy(const SlaveStatus &status) = 0;
private:
int32_t id_ = 0;
};
} // namespace OHOS::NativeRdb
#endif // OHOS_DISTRIBUTED_DATA_RELATIONAL_STORE_FRAMEWORKS_NATIVE_RDB_INCLUDE_CONNECTION_H

View File

@ -1,143 +0,0 @@
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef NATIVE_RDB_SQLITE_CONNECTION_POOL_H
#define NATIVE_RDB_SQLITE_CONNECTION_POOL_H
#include <atomic>
#include <condition_variable>
#include <iostream>
#include <iterator>
#include <list>
#include <memory>
#include <mutex>
#include <sstream>
#include <stack>
#include <vector>
#include "base_transaction.h"
#include "connection.h"
#include "rdb_common.h"
#include "rdb_store_config.h"
namespace OHOS {
namespace NativeRdb {
class ConnectionPool : public std::enable_shared_from_this<ConnectionPool> {
public:
using SharedConn = std::shared_ptr<Connection>;
using SharedConns = std::vector<SharedConn>;
static constexpr std::chrono::milliseconds INVALID_TIME = std::chrono::milliseconds(0);
static std::shared_ptr<ConnectionPool> Create(const RdbStoreConfig &config, int &errCode);
~ConnectionPool();
static std::pair<RebuiltType, std::shared_ptr<ConnectionPool>> HandleDataCorruption
(const RdbStoreConfig &storeConfig, int &errCode);
std::pair<int32_t, std::shared_ptr<Connection>> CreateConnection(bool isReadOnly);
SharedConn AcquireConnection(bool isReadOnly);
SharedConn Acquire(bool isReadOnly, std::chrono::milliseconds ms = INVALID_TIME);
// this interface is only provided for resultSet
SharedConn AcquireRef(bool isReadOnly, std::chrono::milliseconds ms = INVALID_TIME);
std::pair<SharedConn, SharedConns> AcquireAll(int32_t time);
std::pair<int32_t, SharedConn> DisableWal();
int32_t EnableWal();
int RestartReaders();
int ConfigLocale(const std::string &localeStr);
int ChangeDbFileForRestore(const std::string &newPath, const std::string &backupPath,
const std::vector<uint8_t> &newKey, SlaveStatus &slaveStatus);
std::stack<BaseTransaction> &GetTransactionStack();
std::mutex &GetTransactionStackMutex();
int AcquireTransaction();
void ReleaseTransaction();
void CloseAllConnections();
bool IsInTransaction();
void SetInTransaction(bool isInTransaction);
private:
struct ConnNode {
static constexpr uint32_t CHECK_POINT_INTERVAL = 5; // 5 min
bool using_ = false;
int32_t tid_ = 0;
int32_t id_ = 0;
std::chrono::steady_clock::time_point time_ = std::chrono::steady_clock::now();
std::chrono::steady_clock::time_point failedTime_;
std::shared_ptr<Connection> connect_;
explicit ConnNode(std::shared_ptr<Connection> conn);
std::shared_ptr<Connection> GetConnect();
int64_t GetUsingTime() const;
bool IsWriter() const;
int32_t Unused(bool inTrans);
};
struct Container {
using Creator = std::function<std::pair<int32_t, std::shared_ptr<Connection>>()>;
static constexpr int32_t MAX_RIGHT = 0x4FFFFFFF;
bool disable_ = true;
int max_ = 0;
int total_ = 0;
int count_ = 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_;
Creator creator_ = nullptr;
std::pair<int32_t, std::shared_ptr<ConnNode>> Initialize(Creator creator, int32_t max, int32_t timeout,
bool disable, bool acquire = false);
int32_t ConfigLocale(const std::string &locale);
std::shared_ptr<ConnNode> Acquire(std::chrono::milliseconds milliS);
std::list<std::shared_ptr<ConnNode>> AcquireAll(std::chrono::milliseconds milliS);
void Disable();
void Enable();
int32_t Release(std::shared_ptr<ConnNode> node);
int32_t Clear();
bool IsFull();
int32_t Dump(const char *header, bool inTrans);
private:
int32_t ExtendNode();
int32_t RelDetails(std::shared_ptr<ConnNode> node);
};
explicit ConnectionPool(const RdbStoreConfig &storeConfig);
std::pair<int32_t, std::shared_ptr<Connection>> Init(bool isAttach = false, bool needWriter = false);
int32_t GetMaxReaders(const RdbStoreConfig &config);
std::shared_ptr<Connection> Convert2AutoConn(std::shared_ptr<ConnNode> node);
void ReleaseNode(std::shared_ptr<ConnNode> node);
int RestoreByDbSqliteType(const std::string &newPath, const std::string &backupPath, SlaveStatus &slaveStatus);
int RestoreMasterDb(const std::string &newPath, const std::string &backupPath);
bool CheckIntegrity(const std::string &dbPath);
static constexpr int LIMITATION = 1024;
static constexpr uint32_t ITER_V1 = 5000;
static constexpr uint32_t ITERS_COUNT = 2;
const RdbStoreConfig &config_;
RdbStoreConfig attachConfig_;
Container writers_;
Container readers_;
int32_t maxReader_ = 0;
std::stack<BaseTransaction> transactionStack_;
std::mutex transactionStackMutex_;
std::condition_variable transCondition_;
std::mutex transMutex_;
bool transactionUsed_;
std::atomic<bool> isInTransaction_ = false;
};
} // namespace NativeRdb
} // namespace OHOS
#endif

View File

@ -36,38 +36,19 @@ public:
RdbStoreImpl(const RdbStoreConfig &config);
RdbStoreImpl(const RdbStoreConfig &config, int &errCode);
~RdbStoreImpl() override;
const RdbStoreConfig &GetConfig();
int Insert(int64_t &outRowId, const std::string &table, const ValuesBucket &values) override;
int BatchInsert(int64_t& outInsertNum, const std::string& table, const std::vector<ValuesBucket>& values) override;
std::pair<int, int64_t> Insert(const std::string &table, const Row &row, Resolution resolution) override;
std::pair<int, int64_t> BatchInsert(const std::string& table, const ValuesBuckets& values) override;
int Replace(int64_t &outRowId, const std::string &table, const ValuesBucket &initialValues) override;
int InsertWithConflictResolution(int64_t &outRowId, const std::string &table, const ValuesBucket &values,
ConflictResolution conflictResolution) override;
int Update(int &changedRows, const std::string &table, const ValuesBucket &values,
const std::string &whereClause, const std::vector<std::string> &whereArgs) override;
int Update(int &changedRows, const std::string &table, const ValuesBucket &values,
const std::string &whereClause, const std::vector<ValueObject> &bindArgs) override;
int UpdateWithConflictResolution(int &changedRows, const std::string &table, const ValuesBucket &values,
const std::string &whereClause, const std::vector<std::string> &whereArgs,
ConflictResolution conflictResolution) override;
int UpdateWithConflictResolution(int &changedRows, const std::string &table, const ValuesBucket &values,
const std::string &whereClause, const std::vector<ValueObject> &bindArgs,
ConflictResolution conflictResolution) override;
int Delete(int &deletedRows, const std::string &table, const std::string &whereClause,
const std::vector<std::string> &whereArgs) override;
int Delete(int &deletedRows, const std::string &table, const std::string &whereClause,
const std::vector<ValueObject> &bindArgs) override;
int ExecuteSql(const std::string& sql, const std::vector<ValueObject>& bindArgs) override;
std::pair<int32_t, ValueObject> Execute(const std::string &sql, const std::vector<ValueObject> &bindArgs,
int64_t trxId) override;
int ExecuteAndGetLong(int64_t &outValue, const std::string &sql, const std::vector<ValueObject> &bindArgs) override;
int ExecuteAndGetString(std::string &outValue, const std::string &sql,
const std::vector<ValueObject> &bindArgs) override;
int ExecuteForLastInsertedRowId(int64_t &outValue, const std::string &sql,
const std::vector<ValueObject> &bindArgs) override;
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;
std::pair<int, int> Update(const std::string &table, const Row &row, const std::string &where, const Values &args,
Resolution resolution) override;
int Delete(int &deletedRows, const std::string &table, const std::string &whereClause, const Values &args) override;
std::shared_ptr<AbsSharedResultSet> QuerySql(const std::string &sql, const Values &args) override;
std::shared_ptr<ResultSet> QueryByStep(const std::string &sql, const Values &args) override;
int ExecuteSql(const std::string &sql, const Values &args) override;
std::pair<int32_t, ValueObject> Execute(const std::string &sql, const Values &args, int64_t trxId) override;
int ExecuteAndGetLong(int64_t &outValue, const std::string &sql, const Values &args) override;
int ExecuteAndGetString(std::string &outValue, const std::string &sql, const Values &args) override;
int ExecuteForLastInsertedRowId(int64_t &outValue, const std::string &sql, const Values &args) override;
int ExecuteForChangedRowCount(int64_t &outValue, const std::string &sql, const Values &args) override;
int GetVersion(int &version) override;
int SetVersion(int version) override;
int BeginTransaction() override;
@ -83,33 +64,24 @@ public:
bool IsMemoryRdb() const override;
bool IsHoldingConnection() override;
bool IsSlaveDiffFromMaster() const override;
int ConfigLocale(const std::string &localeStr);
int Backup(const std::string &databasePath, const std::vector<uint8_t> &encryptKey) override;
int Restore(const std::string &backupPath, const std::vector<uint8_t> &newKey) override;
std::string GetName();
std::string GetFileType();
std::shared_ptr<ResultSet> QueryByStep(const std::string &sql,
const std::vector<std::string> &sqlArgs) override;
std::shared_ptr<ResultSet> QueryByStep(
const std::string &sql, const std::vector<ValueObject> &args) override;
std::shared_ptr<ResultSet> QueryByStep(
const AbsRdbPredicates &predicates, const std::vector<std::string> &columns) override;
std::shared_ptr<ResultSet> Query(
const AbsRdbPredicates &predicates, const std::vector<std::string> &columns) override;
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;
int GetRebuilt(RebuiltType &rebuilt) 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;
std::pair<int32_t, int32_t> Attach(const RdbStoreConfig &config, const std::string &attachName,
int32_t waitTime) override;
std::pair<int32_t, int32_t> Detach(const std::string &attachName, int32_t waitTime) override;
int InterruptBackup() override;
int32_t GetBackupStatus() const override;
int32_t GetDbType() const override;
std::pair<int32_t, std::shared_ptr<Transaction>> CreateTransaction(int32_t type) override;
const RdbStoreConfig &GetConfig();
int ConfigLocale(const std::string &localeStr);
std::string GetName();
std::string GetFileType();
int32_t ExchangeSlaverToMaster();
private:
using ExecuteSqls = std::vector<std::pair<std::string, std::vector<std::vector<ValueObject>>>>;
using ExecuteSqlsRef =
std::vector<std::pair<std::string, std::vector<std::vector<std::reference_wrapper<ValueObject>>>>>;
using Stmt = std::shared_ptr<Statement>;
using RdbParam = DistributedRdb::RdbSyncerParam;
@ -121,29 +93,20 @@ private:
const std::string &sql, const ValueObject &object, int sqlType);
int CheckAttach(const std::string &sql);
std::pair<int32_t, Stmt> BeginExecuteSql(const std::string &sql);
auto GenerateSql(const std::string& table, const std::vector<ValuesBucket>& buckets, int limit);
auto GenerateSql(const std::string& table, const ValuesBuckets& buckets, int limit);
int GetDataBasePath(const std::string &databasePath, std::string &backupFilePath);
int ExecuteSqlInner(const std::string &sql, const std::vector<ValueObject> &bindArgs);
void SetAssetStatus(const ValueObject &val, int32_t status);
void DoCloudSync(const std::string &table);
int InnerBackup(const std::string &databasePath,
const std::vector<uint8_t> &destEncryptKey = std::vector<uint8_t>());
std::pair<int32_t, Stmt> CreateWriteableStmt(const std::string &sql);
int InnerBackup(const std::string& databasePath,
const std::vector<uint8_t>& destEncryptKey = std::vector<uint8_t>());
std::pair<int32_t, std::shared_ptr<Connection>> CreateWritableConn();
std::vector<ValueObject> CreateBackupBindArgs(const std::string &databasePath,
const std::vector<uint8_t> &destEncryptKey);
std::pair<int32_t, Stmt> GetStatement(const std::string& sql, std::shared_ptr<Connection> conn) const;
std::pair<int32_t, Stmt> GetStatement(const std::string& sql, bool read = false) const;
int AttachInner(const std::string &attachName,
const std::string &dbPath, const std::vector<uint8_t> &key, int32_t waitTime);
int InsertWithConflictResolutionEntry(int64_t &outRowId, const std::string &table, const ValuesBucket &values,
ConflictResolution conflictResolution);
int UpdateWithConflictResolutionEntry(int &changedRows, const std::string &table, const ValuesBucket &values,
const std::string &whereClause, const std::vector<ValueObject> &bindArgs,
ConflictResolution conflictResolution);
template<typename T>
int BatchInsertEntry(const std::string& table, const T& values, size_t rowSize, int64_t& outInsertNum);
int ExecuteSqlEntry(const std::string& sql, const std::vector<ValueObject>& bindArgs);
std::pair<int32_t, ValueObject> ExecuteEntry(const std::string& sql, const std::vector<ValueObject>& bindArgs,
int64_t trxId);
int AttachInner(const RdbStoreConfig &config, const std::string &attachName, const std::string &dbPath,
const std::vector<uint8_t> &key, int32_t waitTime);
int SetDefaultEncryptSql(const std::shared_ptr<Statement> &statement, std::string sql,
const RdbStoreConfig &config);
int SetDefaultEncryptAlgo(const ConnectionPool::SharedConn &conn, const RdbStoreConfig &config);
int GetSlaveName(const std::string &dbName, std::string &backupFilePath);
bool TryGetMasterSlaveBackupPath(const std::string &srcPath, std::string &destPath, bool isRestore = false);
void NotifyDataChange();
@ -153,14 +116,14 @@ private:
static constexpr uint32_t EXPANSION = 2;
static inline constexpr uint32_t INTERVAL = 10;
static inline constexpr uint32_t RETRY_INTERVAL = 5; // s
static inline constexpr uint32_t MAX_RETRY_TIMES = 5;
static inline constexpr int32_t MAX_RETRY_TIMES = 5;
static constexpr const char *ROW_ID = "ROWID";
bool isOpen_ = false;
bool isReadOnly_ = false;
bool isMemoryRdb_;
uint32_t rebuild_;
SlaveStatus slaveStatus_;
uint32_t rebuild_ = RebuiltType::NONE;
SlaveStatus slaveStatus_ = SlaveStatus::UNDEFINED;
int64_t vSchema_ = 0;
std::atomic<int64_t> newTrxId_ = 1;
const RdbStoreConfig config_;
@ -174,9 +137,7 @@ private:
std::set<std::string> cloudTables_;
ConcurrentMap<std::string, std::string> attachedInfo_;
ConcurrentMap<int64_t, std::shared_ptr<Connection>> trxConnMap_ = {};
static inline ValueObject emptyValueObject_;
static inline std::reference_wrapper<ValueObject> emptyValueObjectRef_ = emptyValueObject_;
std::list<std::weak_ptr<Transaction>> transactions_;
};
} // namespace OHOS::NativeRdb
#endif

View File

@ -49,8 +49,8 @@ private:
bool IsConfigInvalidChanged(const std::string &path, RdbStoreConfig &config);
int32_t GetParamFromService(DistributedRdb::RdbSyncerParam &param);
static Param GetSyncParam(const RdbStoreConfig &config);
std::shared_ptr<RdbStoreImpl> GetStoreFromCache(const RdbStoreConfig &config, const std::string &path);
static std::map<std::string, Info> Collector(const RdbStoreConfig &config);
std::shared_ptr<RdbStoreImpl> GetStoreFromCache(const RdbStoreConfig &config, const std::string &path);
static constexpr uint32_t BUCKET_MAX_SIZE = 4;
static const bool regCollector_;

View File

@ -134,7 +134,9 @@ private:
static constexpr int DEFAULT_BUSY_TIMEOUT_MS = 2000;
static constexpr int BACKUP_PAGES_PRE_STEP = 12800; // 1024 * 4 * 12800 == 50m
static constexpr int BACKUP_PRE_WAIT_TIME = 10;
static constexpr ssize_t SLAVE_WAL_SIZE_LIMIT = 2147483647; // 2147483647 = 2g - 1
static constexpr uint32_t NO_ITER = 0;
static constexpr uint32_t WAL_INDEX = 2;
static const int32_t regCreator_;
static const int32_t regRepairer_;
static const int32_t regDeleter_;

View File

@ -1,72 +0,0 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef NATIVE_RDB_STEP_RESULT_SET_H
#define NATIVE_RDB_STEP_RESULT_SET_H
#include <memory>
#include <shared_mutex>
#include <thread>
#include <vector>
#include "abs_result_set.h"
#include "connection.h"
#include "connection_pool.h"
#include "statement.h"
namespace OHOS {
namespace NativeRdb {
class StepResultSet : public AbsResultSet {
public:
StepResultSet(std::shared_ptr<ConnectionPool> pool, const std::string& sql,
const std::vector<ValueObject>& selectionArgs);
~StepResultSet() override;
int GetColumnType(int columnIndex, ColumnType &columnType) override;
int GoToRow(int position) override;
int GoToNextRow() override;
int GetSize(int columnIndex, size_t &size) override;
int Get(int32_t col, ValueObject &value) override;
int Close() override;
int GetRowCount(int &count) override;
protected:
std::pair<int, std::vector<std::string>> GetColumnNames() override;
private:
template<typename T>
int GetValue(int32_t col, T &value);
std::pair<int, ValueObject> GetValueObject(int32_t col, size_t index);
std::shared_ptr<Statement> GetStatement();
int Reset();
int InitRowCount();
int PrepareStep();
// Max times of retrying step query
static const int STEP_QUERY_RETRY_MAX_TIMES = 50;
// Interval of retrying step query in millisecond
static const int STEP_QUERY_RETRY_INTERVAL = 1000;
static const int EMPTY_ROW_COUNT = 0;
bool isSupportCountRow_ = true;
std::shared_ptr<Statement> sqliteStatement_;
std::shared_ptr<Connection> conn_;
std::string sql_;
std::vector<ValueObject> args_;
mutable std::shared_mutex mutex_;
};
} // namespace NativeRdb
} // namespace OHOS
#endif

View File

@ -26,7 +26,6 @@
#include "result_set.h"
#include "sqlite_utils.h"
namespace OHOS {
namespace NativeRdb {
using namespace OHOS::Rdb;
@ -74,7 +73,11 @@ void RowEntity::Clear(int32_t size)
indexs_.resize(size);
}
AbsResultSet::AbsResultSet() : rowPos_(INIT_POS), isClosed_(false), lastErr_(E_OK)
AbsResultSet::AbsResultSet()
{
}
AbsResultSet::AbsResultSet(bool safe) : globalMtx_(safe)
{
}

View File

@ -159,7 +159,7 @@ int32_t ConnPool::GetMaxReaders(const RdbStoreConfig &config)
}
}
std::shared_ptr<Connection> ConnPool::Convert2AutoConn(std::shared_ptr<ConnNode> node)
std::shared_ptr<Connection> ConnPool::Convert2AutoConn(std::shared_ptr<ConnNode> node, bool isTrans)
{
if (node == nullptr) {
return nullptr;
@ -169,12 +169,20 @@ std::shared_ptr<Connection> ConnPool::Convert2AutoConn(std::shared_ptr<ConnNode>
if (conn == nullptr) {
return nullptr;
}
return std::shared_ptr<Connection>(conn.get(), [pool = weak_from_this(), node](Connection *) {
if (isTrans) {
transCount_++;
}
return std::shared_ptr<Connection>(conn.get(), [pool = weak_from_this(), node, isTrans](auto *) mutable {
auto realPool = pool.lock();
if (realPool == nullptr) {
return;
}
realPool->ReleaseNode(node);
if (isTrans) {
realPool->transCount_--;
}
realPool->ReleaseNode(node, !isTrans);
node = nullptr;
});
}
@ -194,9 +202,14 @@ void ConnPool::SetInTransaction(bool isInTransaction)
isInTransaction_.store(isInTransaction);
}
std::pair<int32_t, std::shared_ptr<Connection>> ConnPool::CreateConnection(bool isReadOnly)
std::pair<int32_t, std::shared_ptr<Connection>> ConnPool::CreateTransConn(bool limited)
{
return Connection::Create(config_, true);
if (transCount_ >= MAX_TRANS && limited) {
writers_.Dump("NO TRANS", transCount_ + isInTransaction_);
return { E_DATABASE_BUSY, nullptr };
}
auto [errCode, node] = writers_.Create();
return { errCode, Convert2AutoConn(node, true) };
}
std::shared_ptr<Conn> ConnPool::AcquireConnection(bool isReadOnly)
@ -251,7 +264,7 @@ std::shared_ptr<Conn> ConnPool::Acquire(bool isReadOnly, std::chrono::millisecon
auto node = container->Acquire(ms);
if (node == nullptr) {
const char *header = (isReadOnly && maxReader_ != 0) ? "readers_" : "writers_";
container->Dump(header, isInTransaction_);
container->Dump(header, transCount_ + isInTransaction_);
return nullptr;
}
return Convert2AutoConn(node);
@ -265,7 +278,7 @@ SharedConn ConnPool::AcquireRef(bool isReadOnly, std::chrono::milliseconds ms)
}
auto node = writers_.Acquire(ms);
if (node == nullptr) {
writers_.Dump("writers_", isInTransaction_);
writers_.Dump("writers_", transCount_ + isInTransaction_);
return nullptr;
}
auto conn = node->connect_;
@ -279,20 +292,23 @@ SharedConn ConnPool::AcquireRef(bool isReadOnly, std::chrono::milliseconds ms)
});
}
void ConnPool::ReleaseNode(std::shared_ptr<ConnNode> node)
void ConnPool::ReleaseNode(std::shared_ptr<ConnNode> node, bool reuse)
{
if (node == nullptr) {
return;
}
auto errCode = node->Unused(isInTransaction_);
if (errCode == E_WAL_SIZE_OVER_LIMIT) {
readers_.Dump("WAL Over Limit", isInTransaction_);
auto transCount = transCount_ + isInTransaction_;
auto errCode = node->Unused(transCount);
if (errCode == E_SQLITE_LOCKED || errCode == E_SQLITE_BUSY) {
writers_.Dump("WAL writers_", transCount);
}
if (node->IsWriter()) {
writers_.Release(node);
auto &container = node->IsWriter() ? writers_ : readers_;
if (reuse) {
container.Release(node);
} else {
readers_.Release(node);
container.Drop(node);
}
}
@ -353,7 +369,7 @@ int ConnPool::ChangeDbFileForRestore(const std::string &newPath, const std::stri
}
if (config_.GetDBType() == DB_VECTOR) {
CloseAllConnections();
auto [retVal, connection] = CreateConnection(false);
auto [retVal, connection] = CreateTransConn();
if (connection == nullptr) {
LOG_ERROR("Get null connection.");
@ -436,6 +452,13 @@ int ConnPool::EnableWal()
return errCode;
}
int32_t ConnectionPool::Dump(bool isWriter, const char *header)
{
Container *container = (isWriter || maxReader_ == 0) ? &writers_ : &readers_;
container->Dump(header, transCount_ + isInTransaction_);
return E_OK;
}
ConnPool::ConnNode::ConnNode(std::shared_ptr<Conn> conn) : connect_(std::move(conn))
{
}
@ -453,7 +476,7 @@ int64_t ConnPool::ConnNode::GetUsingTime() const
return duration_cast<milliseconds>(time).count();
}
int32_t ConnPool::ConnNode::Unused(bool inTrans)
int32_t ConnPool::ConnNode::Unused(int32_t count)
{
time_ = steady_clock::now();
if (connect_ == nullptr) {
@ -465,7 +488,7 @@ int32_t ConnPool::ConnNode::Unused(bool inTrans)
tid_ = 0;
}
if (inTrans) {
if (count > 0) {
return E_OK;
}
auto timeout = time_ > (failedTime_ + minutes(CHECK_POINT_INTERVAL)) || time_ < failedTime_;
@ -565,6 +588,28 @@ std::shared_ptr<ConnPool::ConnNode> ConnPool::Container::Acquire(std::chrono::mi
return nullptr;
}
std::pair<int32_t, std::shared_ptr<ConnPool::ConnNode>> ConnPool::Container::Create()
{
if (creator_ == nullptr) {
return { E_NOT_SUPPORT, nullptr };
}
auto [errCode, conn] = creator_();
if (conn == nullptr) {
return { errCode, nullptr };
}
auto node = std::make_shared<ConnNode>(conn);
if (node == nullptr) {
return { E_ERROR, nullptr };
}
node->id_ = MIN_TRANS_ID + trans_;
conn->SetId(node->id_);
details_.push_back(node);
trans_++;
return { E_OK, node };
}
int32_t ConnPool::Container::ExtendNode()
{
if (creator_ == nullptr) {
@ -659,6 +704,16 @@ int32_t ConnPool::Container::Release(std::shared_ptr<ConnNode> node)
return E_OK;
}
int32_t ConnectionPool::Container::Drop(std::shared_ptr<ConnNode> node)
{
{
std::unique_lock<decltype(mutex_)> lock(mutex_);
RelDetails(node);
}
cond_.notify_one();
return E_OK;
}
int32_t ConnectionPool::Container::RelDetails(std::shared_ptr<ConnNode> node)
{
for (auto it = details_.begin(); it != details_.end();) {
@ -677,6 +732,7 @@ bool ConnectionPool::CheckIntegrity(const std::string &dbPath)
RdbStoreConfig config(config_);
config.SetPath(dbPath);
config.SetIntegrityCheck(IntegrityCheck::FULL);
config.SetHaMode(HAMode::SINGLE);
auto [ret, connection] = Connection::Create(config, true);
return ret == E_OK;
}
@ -709,11 +765,11 @@ bool ConnPool::Container::IsFull()
return total_ == count_;
}
int32_t ConnPool::Container::Dump(const char *header, bool inTrans)
int32_t ConnPool::Container::Dump(const char *header, int32_t count)
{
std::string info;
std::vector<std::shared_ptr<ConnNode>> details;
std::string title = "B_M_T_C[" + std::to_string(inTrans) + "," + std::to_string(max_) + "," +
std::string title = "B_M_T_C[" + std::to_string(count) + "," + std::to_string(max_) + "," +
std::to_string(total_) + "," + std::to_string(count_) + "]";
{
std::unique_lock<decltype(mutex_)> lock(mutex_);
@ -737,11 +793,11 @@ int32_t ConnPool::Container::Dump(const char *header, bool inTrans)
.append(">");
// 256 represent that limit to info length
if (info.size() > 256) {
LOG_WARN("%{public}s %{public}s: %{public}s", header, title.c_str(), info.c_str());
LOG_WARN("%{public}s %{public}s:%{public}s", header, title.c_str(), info.c_str());
info.clear();
}
}
LOG_WARN("%{public}s %{public}s: %{public}s", header, title.c_str(), info.c_str());
LOG_WARN("%{public}s %{public}s:%{public}s", header, title.c_str(), info.c_str());
return 0;
}
} // namespace NativeRdb

View File

@ -93,7 +93,7 @@ void DelayNotify::StartTimer()
pool_->Reset(delaySyncTaskId_, std::chrono::milliseconds(autoSyncInterval_));
}
if (autoSyncInterval_ == AUTO_SYNC_INTERVAL || changedData.tableData.empty()) {
if (changedData.tableData.empty()) {
return;
}

View File

@ -522,6 +522,7 @@ RdbPassword RdbSecurityManager::GetRdbPassword(const std::string &dbPath, KeyFil
keyFiles.Lock();
auto &keyFile = keyFiles.GetKeyFile(keyFileType);
if (IsKeyFileEmpty(keyFile)) {
keyFiles.InitKeyPath();
if (!SaveSecretKeyToFile(keyFile)) {
keyFiles.Unlock();
LOG_ERROR("Failed to save key type:%{public}d err:%{public}d.", keyFileType, errno);
@ -643,10 +644,6 @@ int32_t RdbSecurityManager::RestoreKeyFile(const std::string &dbPath, const std:
RdbSecurityManager::KeyFiles::KeyFiles(const std::string &dbPath, bool openFile)
{
const std::string dbKeyDir = StringUtils::ExtractFilePath(dbPath) + "key/";
if (!InitPath(dbKeyDir)) {
LOG_ERROR(
"dbKeyDir failed, errno:%{public}d, dir:%{public}s.", errno, SqliteUtils::Anonymous(dbKeyDir).c_str());
}
const std::string lockDir = StringUtils::ExtractFilePath(dbPath) + "lock/";
if (!InitPath(lockDir)) {
LOG_ERROR("lockDir failed, errno:%{public}d, dir:%{public}s.", errno, SqliteUtils::Anonymous(lockDir).c_str());
@ -681,6 +678,15 @@ const std::string &RdbSecurityManager::KeyFiles::GetKeyFile(KeyFileType type)
return keys_[PUB_KEY_FILE_NEW_KEY];
}
int32_t RdbSecurityManager::KeyFiles::InitKeyPath()
{
const std::string keyDir = StringUtils::ExtractFilePath(keys_[PUB_KEY_FILE]);
if (!InitPath(keyDir)) {
LOG_ERROR("keyDir failed, errno:%{public}d, dir:%{public}s.", errno, SqliteUtils::Anonymous(keyDir).c_str());
}
return E_OK;
}
int32_t RdbSecurityManager::KeyFiles::Lock()
{
if (lockFd_ < 0) {

View File

@ -0,0 +1,603 @@
/*
* 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 "rdb_store.h"
#include "sqlite_sql_builder.h"
#include "sqlite_utils.h"
#include "traits.h"
namespace OHOS::NativeRdb {
RdbStore::ModifyTime::ModifyTime(std::shared_ptr<ResultSet> result, std::map<std::vector<uint8_t>, PRIKey> hashKeys,
bool isFromRowId)
: result_(std::move(result)), hash_(std::move(hashKeys)), isFromRowId_(isFromRowId)
{
for (auto &[_, priKey] : hash_) {
if (priKey.index() != Traits::variant_index_of_v<std::string, PRIKey>) {
break;
}
auto *val = Traits::get_if<std::string>(&priKey);
if (val != nullptr && maxOriginKeySize_ <= val->length()) {
maxOriginKeySize_ = val->length() + 1;
}
}
}
RdbStore::ModifyTime::operator std::map<PRIKey, Date>()
{
if (result_ == nullptr) {
return {};
}
int count = 0;
if (result_->GetRowCount(count) != E_OK || count <= 0) {
return {};
}
std::map<PRIKey, Date> result;
for (int i = 0; i < count; i++) {
result_->GoToRow(i);
int64_t timeStamp = 0;
result_->GetLong(1, timeStamp);
PRIKey index = 0;
if (isFromRowId_) {
int64_t rowid = 0;
result_->GetLong(0, rowid);
index = rowid;
} else {
std::vector<uint8_t> hashKey;
result_->GetBlob(0, hashKey);
index = hash_[hashKey];
}
result[index] = Date(timeStamp);
}
return result;
}
RdbStore::ModifyTime::operator std::shared_ptr<ResultSet>()
{
return result_;
}
RdbStore::PRIKey RdbStore::ModifyTime::GetOriginKey(const std::vector<uint8_t> &hash)
{
auto it = hash_.find(hash);
return it != hash_.end() ? it->second : std::monostate();
}
size_t RdbStore::ModifyTime::GetMaxOriginKeySize()
{
return maxOriginKeySize_;
}
bool RdbStore::ModifyTime::NeedConvert() const
{
return !hash_.empty();
}
static std::vector<ValueObject> ToValues(const std::vector<std::string> &args)
{
std::vector<ValueObject> newArgs;
std::for_each(args.begin(), args.end(), [&newArgs](const auto &it) {
newArgs.push_back(ValueObject(it));
});
return newArgs;
}
static bool ColHasSpecificField(const std::vector<std::string> &columns)
{
for (const std::string &column : columns) {
if (column.find(SqliteUtils::REP) != std::string::npos) {
return true;
}
}
return false;
}
std::pair<int, int64_t> RdbStore::Insert(const std::string &table, const Row &row, Resolution resolution)
{
(void)table;
(void)row;
(void)resolution;
return { E_NOT_SUPPORT, -1 };
}
int RdbStore::Insert(int64_t &outRowId, const std::string &table, const Row &row)
{
auto [errCode, rowid] = Insert(table, row, NO_ACTION);
if (errCode == E_OK) {
outRowId = rowid;
}
return errCode;
}
int RdbStore::InsertWithConflictResolution(int64_t &outRowId, const std::string &table, const Row &row,
Resolution resolution)
{
auto [errCode, rowid] = Insert(table, row, resolution);
if (errCode == E_OK) {
outRowId = rowid;
}
return errCode;
}
int RdbStore::Replace(int64_t &outRowId, const std::string &table, const Row &row)
{
auto [errCode, rowid] = Insert(table, row, Resolution::ON_CONFLICT_REPLACE);
if (errCode == E_OK) {
outRowId = rowid;
}
return errCode;
}
int RdbStore::BatchInsert(int64_t &outInsertNum, const std::string &table, const Rows &rows)
{
ValuesBuckets refRows;
for (auto &row : rows) {
refRows.Put(row);
}
auto [errCode, count] = BatchInsert(table, refRows);
if (errCode == E_OK) {
outInsertNum = count;
}
return errCode;
}
std::pair<int, int64_t> RdbStore::BatchInsert(const std::string &table, const RefRows &rows)
{
return { E_NOT_SUPPORT, -1 };
}
std::pair<int, int> RdbStore::Update(const std::string &table, const Row &row, const std::string &where,
const Values &args, Resolution resolution)
{
(void)table;
(void)row;
(void)where;
(void)args;
(void)resolution;
return { E_NOT_SUPPORT, 0 };
}
int RdbStore::Update(int &changedRows, const std::string &table, const Row &row, const std::string &whereClause,
const Values &args)
{
auto [errCode, changes] = Update(table, row, whereClause, args, NO_ACTION);
if (errCode == E_OK) {
changedRows = changes;
}
return errCode;
}
int RdbStore::Update(int &changedRows, const Row &row, const AbsRdbPredicates &predicates)
{
return Update(changedRows, predicates.GetTableName(), row, predicates.GetWhereClause(), predicates.GetBindArgs());
}
int RdbStore::Update(int &changedRows, const std::string &table, const Row &row, const std::string &whereClause,
const Olds &args)
{
return Update(changedRows, table, row, whereClause, ToValues(args));
};
int RdbStore::UpdateWithConflictResolution(int &changedRows, const std::string &table, const Row &row,
const std::string &whereClause, const Olds &args, Resolution resolution)
{
auto [errCode, changes] = Update(table, row, whereClause, ToValues(args), resolution);
if (errCode == E_OK) {
changedRows = changes;
}
return errCode;
}
int RdbStore::UpdateWithConflictResolution(int &changedRows, const std::string &table, const Row &row,
const std::string &whereClause, const Values &args, Resolution resolution)
{
auto [errCode, changes] = Update(table, row, whereClause, args, resolution);
if (errCode == E_OK) {
changedRows = changes;
}
return errCode;
}
int RdbStore::Delete(int &deletedRows, const std::string &table, const std::string &whereClause, const Olds &args)
{
return Delete(deletedRows, table, whereClause, ToValues(args));
}
int RdbStore::Delete(int &deletedRows, const AbsRdbPredicates &predicates)
{
return Delete(deletedRows, predicates.GetTableName(), predicates.GetWhereClause(), predicates.GetBindArgs());
}
std::shared_ptr<AbsSharedResultSet> RdbStore::Query(int &errCode, bool distinct, const std::string &table,
const Fields &columns, const std::string &whereClause, const Values &args, const std::string &groupBy,
const std::string &indexName, const std::string &orderBy, const int &limit, const int &offset)
{
std::string sql;
errCode = SqliteSqlBuilder::BuildQueryString(distinct, table, "", columns, whereClause, groupBy, indexName,
orderBy, limit, offset, sql);
if (errCode != E_OK) {
return nullptr;
}
return QuerySql(sql, args);
}
std::shared_ptr<AbsSharedResultSet> RdbStore::Query(const AbsRdbPredicates &predicates, const Fields &columns)
{
std::string sql;
std::pair<bool, bool> queryStatus = { ColHasSpecificField(columns), predicates.HasSpecificField() };
if (queryStatus.first || queryStatus.second) {
std::string table = predicates.GetTableName();
std::string logTable = GetLogTableName(table);
sql = SqliteSqlBuilder::BuildCursorQueryString(predicates, columns, logTable, queryStatus);
} else {
sql = SqliteSqlBuilder::BuildQueryString(predicates, columns);
}
return QuerySql(sql, predicates.GetBindArgs());
}
std::shared_ptr<AbsSharedResultSet> RdbStore::QuerySql(const std::string &sql, const Olds &args)
{
return QuerySql(sql, ToValues(args));
}
std::shared_ptr<ResultSet> RdbStore::QueryByStep(const std::string &sql, const Olds &args)
{
return QueryByStep(sql, ToValues(args));
}
std::shared_ptr<ResultSet> RdbStore::QueryByStep(const AbsRdbPredicates &predicates, const RdbStore::Fields &columns)
{
std::string sql;
if (predicates.HasSpecificField()) {
std::string table = predicates.GetTableName();
std::string logTable = GetLogTableName(table);
sql = SqliteSqlBuilder::BuildLockRowQueryString(predicates, columns, logTable);
} else {
sql = SqliteSqlBuilder::BuildQueryString(predicates, columns);
}
return QueryByStep(sql, predicates.GetBindArgs());
}
std::shared_ptr<ResultSet> RdbStore::RemoteQuery(const std::string &device, const AbsRdbPredicates &predicates,
const Fields &columns, int &errCode)
{
(void)device;
(void)predicates;
(void)columns;
errCode = E_NOT_SUPPORT;
return nullptr;
}
std::pair<int32_t, std::shared_ptr<ResultSet>> RdbStore::QuerySharingResource(const AbsRdbPredicates &predicates,
const Fields &columns)
{
(void)predicates;
(void)columns;
return { E_NOT_SUPPORT, nullptr };
}
int RdbStore::ExecuteSql(const std::string &sql, const Values &args)
{
auto [errCode, value] = Execute(sql, args, 0);
return errCode;
}
std::pair<int32_t, ValueObject> RdbStore::Execute(const std::string &sql, const Values &args, int64_t trxId)
{
return { E_NOT_SUPPORT, ValueObject() };
}
int RdbStore::ExecuteAndGetLong(int64_t &outValue, const std::string &sql, const Values &args)
{
auto [errCode, value] = Execute(sql, args);
if (errCode == E_OK) {
outValue = static_cast<int64_t>(value);
}
return errCode;
}
int RdbStore::ExecuteAndGetString(std::string &outValue, const std::string &sql, const Values &args)
{
auto [errCode, value] = Execute(sql, args);
if (errCode == E_OK) {
outValue = static_cast<std::string>(value);
}
return errCode;
}
int RdbStore::ExecuteForLastInsertedRowId(int64_t &outValue, const std::string &sql, const Values &args)
{
auto [errCode, value] = Execute(sql, args);
if (errCode == E_OK) {
(void)value.GetLong(outValue);
}
return errCode;
}
int RdbStore::ExecuteForChangedRowCount(int64_t &outValue, const std::string &sql, const Values &args)
{
auto [errCode, value] = Execute(sql, args);
if (errCode == E_OK) {
(void)value.GetLong(outValue);
}
return errCode;
}
int RdbStore::Backup(const std::string &databasePath, const std::vector<uint8_t> &encryptKey)
{
(void)databasePath;
(void)encryptKey;
return E_NOT_SUPPORT;
}
int RdbStore::Attach(const std::string &alias, const std::string &pathName, const std::vector<uint8_t> encryptKey)
{
(void)alias;
(void)pathName;
(void)encryptKey;
return E_OK;
}
int RdbStore::Count(int64_t &outValue, const AbsRdbPredicates &predicates)
{
(void)outValue;
(void)predicates;
return E_NOT_SUPPORT;
}
std::pair<int32_t, std::shared_ptr<Transaction>> RdbStore::CreateTransaction(int32_t type)
{
(void)type;
return { E_NOT_SUPPORT, nullptr };
}
int RdbStore::BeginTransaction()
{
return E_NOT_SUPPORT;
}
std::pair<int, int64_t> RdbStore::BeginTrans()
{
return { E_NOT_SUPPORT, 0 };
}
int RdbStore::RollBack()
{
return E_NOT_SUPPORT;
}
int RdbStore::RollBack(int64_t trxId)
{
(void)trxId;
return E_NOT_SUPPORT;
}
int RdbStore::Commit()
{
return E_NOT_SUPPORT;
}
int RdbStore::Commit(int64_t trxId)
{
(void)trxId;
return E_NOT_SUPPORT;
}
bool RdbStore::IsInTransaction()
{
return true;
}
std::string RdbStore::GetPath()
{
return "";
}
bool RdbStore::IsHoldingConnection()
{
return true;
}
bool RdbStore::IsOpen() const
{
return true;
}
bool RdbStore::IsReadOnly() const
{
return false;
}
bool RdbStore::IsMemoryRdb() const
{
return false;
}
int RdbStore::Restore(const std::string &backupPath, const std::vector<uint8_t> &newKey)
{
(void)backupPath;
(void)newKey;
return E_NOT_SUPPORT;
}
int RdbStore::SetDistributedTables(const std::vector<std::string> &tables, int32_t type,
const DistributedRdb::DistributedConfig &distributedConfig)
{
(void)tables;
(void)type;
(void)distributedConfig;
return E_NOT_SUPPORT;
}
std::string RdbStore::ObtainDistributedTableName(const std::string &device, const std::string &table, int &errCode)
{
errCode = E_NOT_SUPPORT;
return table + "_" + device;
}
int RdbStore::Sync(const SyncOption &option, const AbsRdbPredicates &predicate, const AsyncBrief &async)
{
(void)option;
(void)predicate;
(void)async;
return E_NOT_SUPPORT;
}
int RdbStore::Sync(const SyncOption &option, const std::vector<std::string> &tables, const AsyncDetail &async)
{
(void)option;
(void)tables;
(void)async;
return E_NOT_SUPPORT;
}
int RdbStore::Sync(const SyncOption &option, const AbsRdbPredicates &predicate, const AsyncDetail &async)
{
(void)option;
(void)predicate;
(void)async;
return E_NOT_SUPPORT;
}
int RdbStore::Subscribe(const SubscribeOption& option, RdbStoreObserver *observer)
{
(void)option;
(void)observer;
return E_NOT_SUPPORT;
}
int RdbStore::UnSubscribe(const SubscribeOption& option, RdbStoreObserver *observer)
{
(void)option;
(void)observer;
return E_NOT_SUPPORT;
}
int RdbStore::SubscribeObserver(const SubscribeOption& option, const std::shared_ptr<RdbStoreObserver> &observer)
{
(void)option;
(void)observer;
return E_NOT_SUPPORT;
}
int RdbStore::UnsubscribeObserver(const SubscribeOption& option, const std::shared_ptr<RdbStoreObserver> &observer)
{
(void)option;
(void)observer;
return E_NOT_SUPPORT;
}
int RdbStore::RegisterAutoSyncCallback(std::shared_ptr<DetailProgressObserver> observer)
{
(void)observer;
return E_NOT_SUPPORT;
}
int RdbStore::UnregisterAutoSyncCallback(std::shared_ptr<DetailProgressObserver> observer)
{
(void)observer;
return E_NOT_SUPPORT;
}
int RdbStore::Notify(const std::string &event)
{
(void)event;
return E_NOT_SUPPORT;
}
bool RdbStore::IsSlaveDiffFromMaster() const
{
return false;
}
int32_t RdbStore::GetDbType() const
{
return DB_SQLITE;
}
std::pair<int32_t, uint32_t> RdbStore::LockCloudContainer()
{
return { E_OK, 0 };
}
int32_t RdbStore::UnlockCloudContainer()
{
return E_OK;
}
int RdbStore::InterruptBackup()
{
return E_OK;
}
int32_t RdbStore::GetBackupStatus() const
{
return SlaveStatus::UNDEFINED;
}
RdbStore::ModifyTime RdbStore::GetModifyTime(const std::string &table, const std::string &column,
std::vector<PRIKey> &keys)
{
(void)table;
(void)column;
(void)keys;
return {};
}
int RdbStore::CleanDirtyData(const std::string &table, uint64_t cursor)
{
(void)table;
(void)cursor;
return E_NOT_SUPPORT;
}
int RdbStore::GetRebuilt(RebuiltType &rebuilt)
{
(void)rebuilt;
return E_NOT_SUPPORT;
}
std::pair<int32_t, int32_t> RdbStore::Attach(const RdbStoreConfig &config, const std::string &attachName,
int32_t waitTime)
{
(void)config;
(void)attachName;
(void)waitTime;
return { E_NOT_SUPPORT, 0 };
}
std::pair<int32_t, int32_t> RdbStore::Detach(const std::string &attachName, int32_t waitTime)
{
(void)attachName;
(void)waitTime;
return { E_NOT_SUPPORT, 0 };
}
int RdbStore::ModifyLockStatus(const AbsRdbPredicates &predicates, bool isLock)
{
(void)predicates;
(void)isLock;
return E_NOT_SUPPORT;
}
int RdbStore::SetSearchable(bool isSearchable)
{
(void)isSearchable;
return E_NOT_SUPPORT;
}
std::string RdbStore::GetLogTableName(const std::string &tableName)
{
return "naturalbase_rdb_aux_" + tableName + "_log";
}
}

File diff suppressed because it is too large Load Diff

View File

@ -43,6 +43,7 @@ using namespace OHOS::Rdb;
using Reportor = RdbFaultHiViewReporter;
__attribute__((used))
const bool RdbStoreManager::regCollector_ = RdbFaultHiViewReporter::RegCollector(RdbStoreManager::Collector);
constexpr int RETRY_INTERVAL = 1;
RdbStoreManager &RdbStoreManager::GetInstance()
{
static RdbStoreManager manager;
@ -71,6 +72,13 @@ std::shared_ptr<RdbStoreImpl> RdbStoreManager::GetStoreFromCache(const RdbStoreC
}
if (!(rdbStore->GetConfig() == config)) {
storeCache_.erase(it);
auto pool = TaskExecutor::GetInstance().GetExecutor();
if (pool != nullptr) {
pool->Schedule(std::chrono::seconds(RETRY_INTERVAL), [config, rdbStore]() {
Reportor::Report(Reportor::Create(config, E_CONFIG_INVALID_CHANGE,
"ErrorType:Config diff!" + RdbStoreConfig::Format(rdbStore->GetConfig(), config)));
});
}
LOG_INFO("app[%{public}s:%{public}s] path[%{public}s]"
" cfg[%{public}d,%{public}d,%{public}d,%{public}d,%{public}d,%{public}d,%{public}d,%{public}s]"
" %{public}s",
@ -87,9 +95,13 @@ std::shared_ptr<RdbStore> RdbStoreManager::GetRdbStore(
const RdbStoreConfig &config, int &errCode, int version, RdbOpenCallback &openCallback)
{
RdbStoreConfig modifyConfig = config;
if (config.IsVector() && config.GetStorageMode() == StorageMode::MODE_MEMORY) {
LOG_ERROR("GetRdbStore type not support memory mode.");
return nullptr;
}
// TOD this lock should only work on storeCache_, add one more lock for connectionpool
std::lock_guard<std::mutex> lock(mutex_);
auto path = modifyConfig.GetRoleType() != OWNER ? modifyConfig.GetVisitorDir() : modifyConfig.GetPath();
auto path = modifyConfig.GetRoleType() == VISITOR ? modifyConfig.GetVisitorDir() : modifyConfig.GetPath();
bundleName_ = modifyConfig.GetBundleName();
std::shared_ptr<RdbStoreImpl> rdbStore = GetStoreFromCache(modifyConfig, path);
if (rdbStore != nullptr) {
@ -99,7 +111,6 @@ std::shared_ptr<RdbStore> RdbStoreManager::GetRdbStore(
errCode = E_CONFIG_INVALID_CHANGE;
return nullptr;
}
rdbStore = std::make_shared<RdbStoreImpl>(modifyConfig, errCode);
if (errCode != E_OK) {
LOG_ERROR("GetRdbStore fail path:%{public}s, rc=%{public}d", SqliteUtils::Anonymous(path).c_str(), errCode);

View File

@ -62,7 +62,9 @@ constexpr const char *SqliteConnection::MERGE_ASSET_FUNC;
constexpr int SqliteConnection::DEFAULT_BUSY_TIMEOUT_MS;
constexpr int SqliteConnection::BACKUP_PAGES_PRE_STEP; // 1024 * 4 * 12800 == 50m
constexpr int SqliteConnection::BACKUP_PRE_WAIT_TIME;
constexpr ssize_t SqliteConnection::SLAVE_WAL_SIZE_LIMIT;
constexpr uint32_t SqliteConnection::NO_ITER;
constexpr uint32_t SqliteConnection::WAL_INDEX;
__attribute__((used))
const int32_t SqliteConnection::regCreator_ = Connection::RegisterCreator(DB_SQLITE, SqliteConnection::Create);
__attribute__((used))
@ -128,6 +130,7 @@ SqliteConnection::SqliteConnection(const RdbStoreConfig &config, bool isWriteCon
: dbHandle_(nullptr), isWriter_(isWriteConnection), isReadOnly_(false), maxVariableNumber_(0), filePath(""),
config_(config)
{
backupId_ = TaskExecutor::INVALID_TASK_ID;
}
int SqliteConnection::CreateSlaveConnection(const RdbStoreConfig &config, bool checkSlaveExist)
@ -135,21 +138,28 @@ int SqliteConnection::CreateSlaveConnection(const RdbStoreConfig &config, bool c
if (config.GetHaMode() != HAMode::MAIN_REPLICA && config.GetHaMode() != HAMode::MANUAL_TRIGGER) {
return E_OK;
}
std::map<std::string, DebugInfo> bugInfo = Connection::Collect(config);
bool isSlaveExist = access(config.GetPath().c_str(), F_OK) == 0;
bool isSlaveLockExist = SqliteUtils::TryAccessSlaveLock(config_.GetPath(), false, false);
bool hasFailure = SqliteUtils::TryAccessSlaveLock(config_.GetPath(), false, false, true);
bool walOverLimit = bugInfo.find(FILE_SUFFIXES[WAL_INDEX].debug_) != bugInfo.end() &&
bugInfo[FILE_SUFFIXES[WAL_INDEX].debug_].size_ > SLAVE_WAL_SIZE_LIMIT;
LOG_INFO("slave cfg:[%{public}d,%{public}d,%{public}d,%{public}d,%{public}d,%{public}d,%{public}d]%{public}s "
"%{public}s,[%{public}d,%{public}d,%{public}d,%{public}d]",
config.GetDBType(), config.GetHaMode(), config.IsEncrypt(), config.GetArea(), config.GetSecurityLevel(),
config.GetRoleType(), config.IsReadOnly(),
Reportor::FormatBrief(bugInfo, SqliteUtils::Anonymous(config.GetName())).c_str(),
Reportor::FormatBrief(Connection::Collect(config_), "master").c_str(), isSlaveExist, isSlaveLockExist,
hasFailure, walOverLimit);
if (config.GetHaMode() == HAMode::MANUAL_TRIGGER &&
(checkSlaveExist && (!isSlaveExist || isSlaveLockExist || hasFailure))) {
LOG_INFO("not dual write on manual, slave:%{public}d, lock:%{public}d, failure:%{public}d", isSlaveExist,
isSlaveLockExist, hasFailure);
(checkSlaveExist && (!isSlaveExist || isSlaveLockExist || hasFailure || walOverLimit))) {
if (walOverLimit) {
SqliteUtils::TryAccessSlaveLock(config_.GetPath(), false, true, true);
}
return E_OK;
}
std::shared_ptr<SqliteConnection> connection = std::make_shared<SqliteConnection>(config, true);
LOG_INFO("slave cfg:[%{public}d,%{public}d,%{public}d,%{public}d,%{public}d,%{public}d,%{public}d]%{public}s",
config.GetDBType(), config.GetHaMode(), config.IsEncrypt(), config.GetArea(), config.GetSecurityLevel(),
config.GetRoleType(), config.IsReadOnly(),
Reportor::FormatBrief(Connection::Collect(config), SqliteUtils::Anonymous(config.GetName())).c_str());
int errCode = connection->InnerOpen(config);
if (errCode != E_OK) {
SqliteUtils::TryAccessSlaveLock(config_.GetPath(), false, true, true);
@ -955,7 +965,7 @@ int SqliteConnection::TryCheckPoint(bool timeout)
if (errCode != SQLITE_OK) {
LOG_WARN("sqlite3_wal_checkpoint_v2 failed err:%{public}d,size:%{public}zd,wal:%{public}s.", errCode, size,
SqliteUtils::Anonymous(walName).c_str());
return E_ERROR;
return SQLiteError::ErrNo(errCode);
}
return E_OK;
}

View File

@ -20,6 +20,7 @@
#include <chrono>
#include <cerrno>
#include <cinttypes>
#include <cstring>
#include "logger.h"
#include "sqlite3sym.h"
#include "sqlite_utils.h"

View File

@ -36,40 +36,36 @@
namespace OHOS {
namespace NativeRdb {
using namespace OHOS::Rdb;
using namespace std::chrono;
constexpr int64_t TIME_OUT = 1500;
SqliteSharedResultSet::SqliteSharedResultSet(std::shared_ptr<ConnectionPool> pool, std::string path,
std::string sql, const std::vector<ValueObject>& bindArgs)
: AbsSharedResultSet(path), isOnlyFillBlock_(false), blockCapacity_(0), qrySql_(std::move(sql)),
bindArgs_(std::move(bindArgs))
SqliteSharedResultSet::SqliteSharedResultSet(Time start, Conn conn, std::string sql, const Values &args,
const std::string &path)
: AbsSharedResultSet(path), conn_(std::move(conn)), qrySql_(std::move(sql)), bindArgs_(args)
{
auto queryStart = std::chrono::steady_clock::now();
conn_ = pool->AcquireRef(true);
if (conn_ == nullptr) {
isClosed_ = true;
return;
}
auto preparStart = std::chrono::steady_clock::now();
auto prepareBegin = steady_clock::now();
auto [statement, errCode] = PrepareStep();
if (errCode != E_OK) {
LOG_ERROR("step resultset ret %{public}d", errCode);
return;
}
statement_ = statement;
auto initCountStart = std::chrono::steady_clock::now();
auto countBegin = steady_clock::now();
rowCount_ = InitRowCount();
auto queryEnd = std::chrono::steady_clock::now();
int64_t totalCostTime = std::chrono::duration_cast<std::chrono::milliseconds>(queryEnd - queryStart).count();
if (totalCostTime >= TIME_OUT) {
int64_t acquirCost = std::chrono::duration_cast<std::chrono::milliseconds>(preparStart - queryStart).count();
int64_t preparCost =
std::chrono::duration_cast<std::chrono::milliseconds>(initCountStart - preparStart).count();
int64_t initCountCost =
std::chrono::duration_cast<std::chrono::milliseconds>(queryEnd - initCountStart).count();
LOG_WARN("query totalCostTime[%{public}" PRId64 "] acquirCost[%{public}" PRId64 "] preparCost[%{public}" PRId64
"] "
"initCountCost[%{public}" PRId64 "] rowCount[%{public}d] sql[%{public}s] path[%{public}s]",
totalCostTime, acquirCost, preparCost, initCountCost, rowCount_, qrySql_.c_str(), path.c_str());
auto endTime = steady_clock::now();
int64_t totalCost = duration_cast<milliseconds>(endTime - start).count();
if (totalCost >= TIME_OUT) {
int64_t acquireCost = duration_cast<milliseconds>(prepareBegin - start).count();
int64_t prepareCost = duration_cast<milliseconds>(countBegin - prepareBegin).count();
int64_t countCost = duration_cast<milliseconds>(endTime - countBegin).count();
LOG_WARN("total[%{public}" PRId64 "]<%{public}" PRId64 ",%{public}" PRId64 ",%{public}" PRId64
"> rowCount[%{public}d] sql[%{public}s] path[%{public}s]",
totalCost, acquireCost, prepareCost, countCost, rowCount_, qrySql_.c_str(),
SqliteUtils::Anonymous(path).c_str());
}
}
@ -224,7 +220,7 @@ int SqliteSharedResultSet::FillBlock(int requiredPos)
|| block->GetStartPos() > 0) {
LOG_WARN("blockRowNum=%{public}d, requiredPos= %{public}d, startPos_= %{public}" PRIu32
", lastPos_= %{public}" PRIu32 ", blockPos_= %{public}" PRIu32 ".",
rowCount_, requiredPos, block->GetStartPos(), block->GetLastPos(), block->GetBlockPos());
rowCount_, requiredPos, block->GetStartPos(), block->GetLastPos(), block->GetBlockPos());
}
return E_OK;
}

View File

@ -23,13 +23,16 @@
#include "rdb_trace.h"
#include "string_utils.h"
#include "sqlite_utils.h"
#include "traits.h"
namespace OHOS {
namespace NativeRdb {
using namespace OHOS::Rdb;
std::vector<std::string> g_onConflictClause = {
"", " OR ROLLBACK", " OR ABORT", " OR FAIL", " OR IGNORE", " OR REPLACE"
};
ValueObject SqliteSqlBuilder::nullObject_;
std::reference_wrapper<ValueObject> SqliteSqlBuilder::nullRef_ = SqliteSqlBuilder::nullObject_;
SqliteSqlBuilder::SqliteSqlBuilder() {}
SqliteSqlBuilder::~SqliteSqlBuilder() {}
@ -334,17 +337,42 @@ std::string SqliteSqlBuilder::GetSqlArgs(size_t size)
return args;
}
template<typename T>
SqliteSqlBuilder::ExecuteSqlsType<T> SqliteSqlBuilder::MakeExecuteSqls(
const std::string &sql, const std::vector<T> &args, int fieldSize, int limit)
SqliteSqlBuilder::BatchRefSqls SqliteSqlBuilder::GenerateSqls(const std::string &table, const ValuesBuckets &buckets,
int limit)
{
auto [fields, values] = buckets.GetFieldsAndValues();
auto columnSize = fields->size();
auto rowSize = buckets.RowSize();
std::vector<std::reference_wrapper<ValueObject>> args(columnSize * rowSize, nullRef_);
std::string sql = "INSERT OR REPLACE INTO " + table + " (";
size_t columnIndex = 0;
for (auto &field : *fields) {
for (size_t row = 0; row < rowSize; ++row) {
auto [errorCode, value] = buckets.Get(row, std::ref(field));
if (errorCode != E_OK) {
continue;
}
SqliteSqlBuilder::UpdateAssetStatus(value.get(), AssetValue::STATUS_INSERT);
args[columnIndex + row * columnSize] = value;
}
columnIndex++;
sql.append(field).append(",");
}
sql.pop_back();
sql.append(") VALUES ");
return SqliteSqlBuilder::MakeExecuteSqls(sql, args, columnSize, limit);
}
SqliteSqlBuilder::BatchRefSqls SqliteSqlBuilder::MakeExecuteSqls(const std::string &sql,
const std::vector<RefValue> &args, int fieldSize, int limit)
{
if (fieldSize == 0) {
return ExecuteSqlsType<T>();
return BatchRefSqls();
}
size_t rowNumbers = args.size() / static_cast<size_t>(fieldSize);
size_t maxRowNumbersOneTimes = static_cast<size_t>(limit / fieldSize);
if (maxRowNumbersOneTimes == 0) {
return ExecuteSqlsType<T>();
return BatchRefSqls();
}
size_t executeTimes = rowNumbers / maxRowNumbersOneTimes;
size_t remainingRows = rowNumbers % maxRowNumbersOneTimes;
@ -358,14 +386,14 @@ SqliteSqlBuilder::ExecuteSqlsType<T> SqliteSqlBuilder::MakeExecuteSqls(
return sqlStr;
};
std::string executeSql;
ExecuteSqlsType<T> executeSqls;
BatchRefSqls executeSqls;
auto start = args.begin();
if (executeTimes != 0) {
executeSql = appendAgsSql(maxRowNumbersOneTimes);
std::vector<std::vector<T>> sqlArgs;
std::vector<std::vector<RefValue>> sqlArgs;
size_t maxVariableNumbers = maxRowNumbersOneTimes * static_cast<size_t>(fieldSize);
for (size_t i = 0; i < executeTimes; ++i) {
std::vector<T> bindValueArgs(start, start + maxVariableNumbers);
std::vector<RefValue> bindValueArgs(start, start + maxVariableNumbers);
sqlArgs.emplace_back(std::move(bindValueArgs));
start += maxVariableNumbers;
}
@ -374,15 +402,40 @@ SqliteSqlBuilder::ExecuteSqlsType<T> SqliteSqlBuilder::MakeExecuteSqls(
if (remainingRows != 0) {
executeSql = appendAgsSql(remainingRows);
std::vector<std::vector<T>> sqlArgs(1, std::vector<T>(start, args.end()));
std::vector<std::vector<RefValue>> sqlArgs(1, std::vector<RefValue>(start, args.end()));
executeSqls.emplace_back(std::make_pair(executeSql, std::move(sqlArgs)));
}
return executeSqls;
}
template SqliteSqlBuilder::ExecuteSqlsType<ValueObject> SqliteSqlBuilder::MakeExecuteSqls(
const std::string &sql, const std::vector<ValueObject> &args, int fieldSize, int limit);
template SqliteSqlBuilder::ExecuteSqlsType<std::reference_wrapper<ValueObject>> SqliteSqlBuilder::MakeExecuteSqls(
const std::string &sql, const std::vector<std::reference_wrapper<ValueObject>> &args, int fieldSize, int limit);
std::string SqliteSqlBuilder::HandleTable(const std::string &tableName)
{
if (tableName.empty()) {
return tableName;
}
std::regex validName("^([a-zA-Z_][a-zA-Z0-9_\\.\\ ]*)$");
if (std::regex_match(tableName, validName)) {
return tableName;
}
return "'" + tableName + "'";
}
void SqliteSqlBuilder::UpdateAssetStatus(const ValueObject &val, int32_t status)
{
if (val.GetType() == ValueObject::TYPE_ASSET) {
auto *asset = Traits::get_if<ValueObject::Asset>(&val.value);
if (asset != nullptr) {
asset->status = static_cast<AssetValue::Status>(status);
}
}
if (val.GetType() == ValueObject::TYPE_ASSETS) {
auto *assets = Traits::get_if<ValueObject::Assets>(&val.value);
if (assets != nullptr) {
for (auto &asset : *assets) {
asset.status = static_cast<AssetValue::Status>(status);
}
}
}
}
} // namespace NativeRdb
} // namespace OHOS

View File

@ -29,21 +29,23 @@
namespace OHOS {
namespace NativeRdb {
using namespace OHOS::Rdb;
StepResultSet::StepResultSet(std::shared_ptr<ConnectionPool> pool, const std::string &sql,
const std::vector<ValueObject> &args)
: AbsResultSet(), sql_(sql), args_(std::move(args))
constexpr int64_t TIME_OUT = 1500;
StepResultSet::StepResultSet(Time start, Conn conn, const std::string &sql, const Values &args, bool safe)
: AbsResultSet(safe), conn_(std::move(conn)), sql_(sql), args_(args)
{
conn_ = pool->AcquireRef(true);
if (conn_ == nullptr) {
isClosed_ = true;
return;
}
auto prepareStart = std::chrono::steady_clock::now();
auto errCode = PrepareStep();
if (errCode != E_OK) {
LOG_ERROR("step resultset ret %{public}d", errCode);
return;
}
auto prepareEnd = std::chrono::steady_clock::now();
auto statement = GetStatement();
if (statement == nullptr) {
return;
@ -53,6 +55,16 @@ StepResultSet::StepResultSet(std::shared_ptr<ConnectionPool> pool, const std::st
isSupportCountRow_ = false;
lastErr_ = E_OK;
}
auto queryEnd = std::chrono::steady_clock::now();
int64_t totalCost = std::chrono::duration_cast<std::chrono::milliseconds>(queryEnd - start).count();
if (totalCost >= TIME_OUT) {
int64_t acquireCost = std::chrono::duration_cast<std::chrono::milliseconds>(prepareStart - start).count();
int64_t prepareCost = std::chrono::duration_cast<std::chrono::milliseconds>(prepareEnd - prepareStart).count();
int64_t countCost = std::chrono::duration_cast<std::chrono::milliseconds>(queryEnd - prepareEnd).count();
LOG_WARN("total[%{public}" PRId64 "]<%{public}" PRId64 ",%{public}" PRId64 ",%{public}" PRId64
"> count[%{public}d] sql[%{public}s]",
totalCost, acquireCost, prepareCost, countCost, rowCount_, SqliteUtils::Anonymous(sql_).c_str());
}
}
StepResultSet::~StepResultSet()
@ -91,18 +103,19 @@ int StepResultSet::InitRowCount()
*/
int StepResultSet::PrepareStep()
{
if (sqliteStatement_ != nullptr) {
std::lock_guard<decltype(globalMtx_)> lockGuard(globalMtx_);
if (statement_ != nullptr) {
return E_OK;
}
if (conn_ == nullptr) {
if (isClosed_ || conn_ == nullptr) {
lastErr_ = E_ALREADY_CLOSED;
return lastErr_;
}
auto type = SqliteUtils::GetSqlStatementType(sql_);
if (type == SqliteUtils::STATEMENT_ERROR) {
LOG_ERROR("invalid sql_ %{public}s!", sql_.c_str());
LOG_ERROR("invalid sql_ %{public}s!", SqliteUtils::Anonymous(sql_).c_str());
lastErr_ = E_INVALID_ARGS;
return lastErr_;
}
@ -128,10 +141,7 @@ int StepResultSet::PrepareStep()
return lastErr_;
}
sqliteStatement_ = std::move(statement);
if (sqliteStatement_ == nullptr) {
LOG_ERROR("sqliteStatement_ is nullptr.");
}
statement_ = std::move(statement);
return E_OK;
}
@ -280,9 +290,13 @@ int StepResultSet::Close()
return E_OK;
}
isClosed_ = true;
conn_ = nullptr;
sqliteStatement_ = nullptr;
auto args = std::move(args_);
{
std::lock_guard<decltype(globalMtx_)> lockGuard(globalMtx_);
conn_ = nullptr;
statement_ = nullptr;
auto args = std::move(args_);
auto sql = std::move(sql_);
}
Reset();
return E_OK;
}
@ -380,11 +394,12 @@ std::pair<int, ValueObject> StepResultSet::GetValueObject(int32_t col, size_t in
std::shared_ptr<Statement> StepResultSet::GetStatement()
{
std::lock_guard<decltype(globalMtx_)> lockGuard(globalMtx_);
if (isClosed_ || conn_ == nullptr) {
return nullptr;
}
return sqliteStatement_;
return statement_;
}
} // namespace NativeRdb
} // namespace OHOS

View File

@ -0,0 +1,269 @@
/*
* Copyright (c) 2024 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define LOG_TAG "TransDB"
#include "trans_db.h"
#include "logger.h"
#include "rdb_sql_statistic.h"
#include "rdb_trace.h"
#include "sqlite_sql_builder.h"
#include "sqlite_utils.h"
#include "step_result_set.h"
#if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM)
#include "sqlite_shared_result_set.h"
#endif
namespace OHOS::NativeRdb {
using namespace OHOS::Rdb;
using namespace DistributedRdb;
TransDB::TransDB(std::shared_ptr<Connection> conn, const std::string &name) : conn_(conn), name_(name)
{
maxArgs_ = conn->GetMaxVariable();
}
std::pair<int, int64_t> TransDB::Insert(const std::string &table, const Row &row, Resolution resolution)
{
DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__));
auto conflictClause = SqliteUtils::GetConflictClause(static_cast<int>(resolution));
if (table.empty() || row.IsEmpty() || conflictClause == nullptr) {
return { E_INVALID_ARGS, -1 };
}
std::string sql("INSERT");
sql.append(conflictClause).append(" INTO ").append(table).append("(");
std::vector<ValueObject> args;
args.reserve(row.values_.size());
const char *split = "";
for (const auto &[key, val] : row.values_) {
sql.append(split).append(key);
if (val.GetType() == ValueObject::TYPE_ASSETS && resolution == ConflictResolution::ON_CONFLICT_REPLACE) {
return { E_INVALID_ARGS, -1 };
}
SqliteSqlBuilder::UpdateAssetStatus(val, AssetValue::STATUS_INSERT);
args.push_back(val); // columnValue
split = ",";
}
sql.append(") VALUES (");
if (!args.empty()) {
sql.append(SqliteSqlBuilder::GetSqlArgs(args.size()));
}
sql.append(")");
int64_t rowid = -1;
auto [errCode, statement] = GetStatement(sql);
if (statement == nullptr) {
return { errCode, rowid };
}
errCode = statement->Execute(args);
if (errCode != E_OK) {
return { errCode, rowid };
}
rowid = statement->Changes() > 0 ? statement->LastInsertRowId() : -1;
return { errCode, rowid };
}
std::pair<int, int64_t> TransDB::BatchInsert(const std::string &table, const RefRows &rows)
{
if (rows.RowSize() == 0) {
return { E_OK, 0 };
}
auto batchInfo = SqliteSqlBuilder::GenerateSqls(table, rows, maxArgs_);
if (table.empty() || batchInfo.empty()) {
LOG_ERROR("empty,table=%{public}s,rows:%{public}zu,max:%{public}d.", table.c_str(), rows.RowSize(), maxArgs_);
return { E_INVALID_ARGS, -1 };
}
for (const auto &[sql, batchArgs] : batchInfo) {
auto [errCode, statement] = GetStatement(sql);
if (statement == nullptr) {
return { errCode, -1 };
}
for (const auto &args : batchArgs) {
errCode = statement->Execute(args);
if (errCode == E_OK) {
continue;
}
LOG_ERROR("failed(0x%{public}x) db:%{public}s table:%{public}s args:%{public}zu", errCode,
SqliteUtils::Anonymous(name_).c_str(), table.c_str(), args.size());
return { errCode, -1 };
}
}
return { E_OK, int64_t(rows.RowSize()) };
}
std::pair<int, int> TransDB::Update(const std::string &table, const Row &row, const std::string &where,
const Values &args, Resolution resolution)
{
DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__));
auto clause = SqliteUtils::GetConflictClause(static_cast<int>(resolution));
if (table.empty() || row.IsEmpty() || clause == nullptr) {
return { E_INVALID_ARGS, 0 };
}
std::string sql("UPDATE");
sql.append(clause).append(" ").append(table).append(" SET ");
std::vector<ValueObject> totalArgs;
totalArgs.reserve(row.values_.size() + args.size());
const char *split = "";
for (auto &[key, val] : row.values_) {
sql.append(split);
if (val.GetType() == ValueObject::TYPE_ASSETS) {
sql.append(key).append("=merge_assets(").append(key).append(", ?)");
} else if (val.GetType() == ValueObject::TYPE_ASSET) {
sql.append(key).append("=merge_asset(").append(key).append(", ?)");
} else {
sql.append(key).append("=?");
}
totalArgs.push_back(val);
split = ",";
}
if (!where.empty()) {
sql.append(" WHERE ").append(where);
}
totalArgs.insert(totalArgs.end(), args.begin(), args.end());
auto [errCode, statement] = GetStatement(sql);
if (statement == nullptr) {
return { errCode, 0 };
}
errCode = statement->Execute(totalArgs);
if (errCode != E_OK) {
return { errCode, 0 };
}
return { errCode, int32_t(statement->Changes()) };
}
int TransDB::Delete(int &deletedRows, const std::string &table, const std::string &whereClause, const Values &args)
{
DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__));
if (table.empty()) {
return E_INVALID_ARGS;
}
std::string sql;
sql.append("DELETE FROM ").append(table);
if (!whereClause.empty()) {
sql.append(" WHERE ").append(whereClause);
}
auto [errCode, statement] = GetStatement(sql);
if (statement == nullptr) {
return errCode;
}
errCode = statement->Execute(args);
if (errCode != E_OK) {
return errCode;
}
deletedRows = statement->Changes();
return E_OK;
}
std::shared_ptr<AbsSharedResultSet> TransDB::QuerySql(const std::string &sql, const Values &args)
{
#if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM)
auto start = std::chrono::steady_clock::now();
return std::make_shared<SqliteSharedResultSet>(start, conn_.lock(), sql, args, name_);
#else
(void)sql;
(void)args;
return nullptr;
#endif
}
std::shared_ptr<ResultSet> TransDB::QueryByStep(const std::string &sql, const Values &args)
{
auto start = std::chrono::steady_clock::now();
return std::make_shared<StepResultSet>(start, conn_.lock(), sql, args, true);
}
std::pair<int32_t, ValueObject> TransDB::Execute(const std::string &sql, const Values &args, int64_t trxId)
{
(void)trxId;
ValueObject object;
int sqlType = SqliteUtils::GetSqlStatementType(sql);
if (!SqliteUtils::IsSupportSqlForExecute(sqlType) && !SqliteUtils::IsSpecial(sqlType)) {
LOG_ERROR("Not support the sql:%{public}s", sql.c_str());
return { E_INVALID_ARGS, object };
}
auto [errCode, statement] = GetStatement(sql);
if (errCode != E_OK) {
return { errCode, object };
}
errCode = statement->Execute(args);
if (errCode != E_OK) {
LOG_ERROR("failed,sql:%{public}s, error:0x%{public}x.", sql.c_str(), errCode);
return { errCode, object };
}
if (sqlType == SqliteUtils::STATEMENT_INSERT) {
int64_t outValue = statement->Changes() > 0 ? statement->LastInsertRowId() : -1;
return { errCode, ValueObject(outValue) };
}
if (sqlType == SqliteUtils::STATEMENT_UPDATE) {
int outValue = statement->Changes();
return { errCode, ValueObject(outValue) };
}
if (sqlType == SqliteUtils::STATEMENT_PRAGMA) {
if (statement->GetColumnCount() == 1) {
return statement->GetColumn(0);
}
}
if (sqlType == SqliteUtils::STATEMENT_DDL) {
statement->Reset();
statement->Prepare("PRAGMA schema_version");
auto [err, version] = statement->ExecuteForValue();
if (vSchema_ < static_cast<int64_t>(version)) {
LOG_INFO("db:%{public}s exe DDL schema<%{public}" PRIi64 "->%{public}" PRIi64 "> sql:%{public}s.",
SqliteUtils::Anonymous(name_).c_str(), vSchema_, static_cast<int64_t>(version), sql.c_str());
vSchema_ = version;
}
}
return { errCode, object };
}
int TransDB::GetVersion(int &version)
{
return E_NOT_SUPPORT;
}
int TransDB::SetVersion(int version)
{
return E_NOT_SUPPORT;
}
int TransDB::Sync(const SyncOption &option, const std::vector<std::string> &tables, const AsyncDetail &async)
{
if (option.mode != TIME_FIRST || tables.empty()) {
return E_INVALID_ARGS;
}
return RdbStore::Sync(option, tables, async);
}
std::pair<int32_t, std::shared_ptr<Statement>> TransDB::GetStatement(const std::string &sql) const
{
auto connection = conn_.lock();
if (connection == nullptr) {
return { E_ALREADY_CLOSED, nullptr };
}
return connection->CreateStatement(sql, connection);
}
} // namespace OHOS::NativeRdb

View File

@ -0,0 +1,32 @@
/*
* 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 "transaction.h"
namespace OHOS::NativeRdb {
std::pair<int32_t, std::shared_ptr<Transaction>> Transaction::Create(
int32_t type, std::shared_ptr<Connection> connection, const std::string &name)
{
if (creator_ != nullptr) {
return creator_(type, std::move(connection), name);
}
return { E_ERROR, nullptr };
}
int32_t Transaction::RegisterCreator(Creator creator)
{
creator_ = std::move(creator);
return E_OK;
}
}

View File

@ -0,0 +1,290 @@
/*
* Copyright (c) 2024 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define LOG_TAG "TransactionImpl"
#include "transaction_impl.h"
#include "logger.h"
#include "rdb_errno.h"
#include "rdb_store.h"
#include "trans_db.h"
using namespace OHOS::Rdb;
namespace OHOS::NativeRdb {
__attribute__((used))
const int32_t TransactionImpl::regCreator_ = Transaction::RegisterCreator(TransactionImpl::Create);
TransactionImpl::TransactionImpl(std::shared_ptr<Connection> connection, const std::string &name)
: name_(name), connection_(std::move(connection))
{
LOG_INFO("constructor name=%{public}s", name_.c_str());
}
TransactionImpl::~TransactionImpl()
{
LOG_INFO("destructor name=%{public}s", name_.c_str());
CloseInner();
}
std::pair<int32_t, std::shared_ptr<Transaction>> TransactionImpl::Create(
int32_t type, std::shared_ptr<Connection> connection, const std::string &name)
{
auto trans = std::make_shared<TransactionImpl>(std::move(connection), name);
if (trans == nullptr) {
return { E_ERROR, nullptr };
}
auto errorCode = trans->Begin(type);
if (errorCode != E_OK) {
LOG_ERROR("transaction begin failed, errorCode=%{public}d", errorCode);
return { errorCode, nullptr };
}
return { E_OK, trans };
}
std::string TransactionImpl::GetBeginSql(int32_t type)
{
if (type < TransactionType::DEFERRED || type >= static_cast<int32_t>(TransactionType::TRANS_BUTT)) {
LOG_ERROR("invalid type=%{public}d", type);
return {};
}
return BEGIN_SQLS[type];
}
int32_t TransactionImpl::Begin(int32_t type)
{
LOG_INFO("type=%{public}d", static_cast<int32_t>(type));
std::lock_guard lock(mutex_);
store_ = std::make_shared<TransDB>(connection_, name_);
if (store_ == nullptr) {
return E_ERROR;
}
auto beginSql = GetBeginSql(type);
if (beginSql.empty()) {
CloseInner();
return E_INVALID_ARGS;
}
auto [errorCode, statement] = connection_->CreateStatement(beginSql, connection_);
if (errorCode != E_OK) {
LOG_ERROR("create statement failed, errorCode=%{public}d", errorCode);
CloseInner();
return errorCode;
}
errorCode = statement->Execute();
if (errorCode != E_OK) {
LOG_ERROR("statement execute failed, errorCode=%{public}d", errorCode);
CloseInner();
return errorCode;
}
return E_OK;
}
int32_t TransactionImpl::Commit()
{
std::lock_guard lock(mutex_);
if (connection_ == nullptr) {
LOG_ERROR("connection already closed");
return E_ALREADY_CLOSED;
}
auto [errorCode, statement] = connection_->CreateStatement(COMMIT_SQL, connection_);
if (errorCode != E_OK) {
LOG_ERROR("create statement failed, errorCode=%{public}d", errorCode);
CloseInner();
return errorCode;
}
errorCode = statement->Execute();
CloseInner();
if (errorCode != E_OK) {
LOG_ERROR("statement execute failed, errorCode=%{public}d", errorCode);
return errorCode;
}
return E_OK;
}
int32_t TransactionImpl::Rollback()
{
std::lock_guard lock(mutex_);
if (connection_ == nullptr) {
LOG_ERROR("connection already closed");
return E_ALREADY_CLOSED;
}
auto [errorCode, statement] = connection_->CreateStatement(ROLLBACK_SQL, connection_);
if (errorCode != E_OK) {
LOG_ERROR("create statement failed, errorCode=%{public}d", errorCode);
CloseInner();
return errorCode;
}
errorCode = statement->Execute();
CloseInner();
if (errorCode != E_OK) {
LOG_ERROR("statement execute failed, errorCode=%{public}d", errorCode);
return errorCode;
}
return E_OK;
}
int32_t TransactionImpl::CloseInner()
{
std::lock_guard lock(mutex_);
store_ = nullptr;
connection_ = nullptr;
for (auto &resultSet : resultSets_) {
auto sp = resultSet.lock();
if (sp != nullptr) {
sp->Close();
}
}
return E_OK;
}
int32_t TransactionImpl::Close()
{
return CloseInner();
}
std::shared_ptr<RdbStore> TransactionImpl::GetStore()
{
std::lock_guard lock(mutex_);
return store_;
}
std::pair<int, int64_t> TransactionImpl::Insert(const std::string &table, const Row &row, Resolution resolution)
{
auto store = GetStore();
if (store == nullptr) {
LOG_ERROR("transaction already close");
return { E_ALREADY_CLOSED, -1 };
}
return store->Insert(table, row, resolution);
}
std::pair<int32_t, int64_t> TransactionImpl::BatchInsert(const std::string &table, const Rows &rows)
{
auto store = GetStore();
if (store == nullptr) {
LOG_ERROR("transaction already close");
return { E_ALREADY_CLOSED, -1 };
}
int64_t insertRows{};
auto errorCode = store->BatchInsert(insertRows, table, rows);
return { errorCode, insertRows };
}
std::pair<int, int64_t> TransactionImpl::BatchInsert(const std::string &table, const RefRows &rows)
{
auto store = GetStore();
if (store == nullptr) {
LOG_ERROR("transaction already close");
return { E_ALREADY_CLOSED, -1 };
}
return store->BatchInsert(table, rows);
}
std::pair<int, int> TransactionImpl::Update(const std::string &table, const Row &row, const std::string &where,
const Values &args, Resolution resolution)
{
auto store = GetStore();
if (store == nullptr) {
LOG_ERROR("transaction already close");
return { E_ALREADY_CLOSED, -1 };
}
return store->Update(table, row, where, args, resolution);
}
std::pair<int32_t, int32_t> TransactionImpl::Update(const Row &row, const AbsRdbPredicates &predicates,
Resolution resolution)
{
auto store = GetStore();
if (store == nullptr) {
LOG_ERROR("transaction already close");
return { E_ALREADY_CLOSED, -1 };
}
return store->Update(predicates.GetTableName(), row, predicates.GetWhereClause(), predicates.GetBindArgs(),
resolution);
}
std::pair<int32_t, int32_t> TransactionImpl::Delete(const std::string &table, const std::string &whereClause,
const Values &args)
{
auto store = GetStore();
if (store == nullptr) {
LOG_ERROR("transaction already close");
return { E_ALREADY_CLOSED, -1 };
}
int deletedRows{};
auto errorCode = store->Delete(deletedRows, table, whereClause, args);
return { errorCode, deletedRows };
}
std::pair<int32_t, int32_t> TransactionImpl::Delete(const AbsRdbPredicates &predicates)
{
auto store = GetStore();
if (store == nullptr) {
LOG_ERROR("transaction already close");
return { E_ALREADY_CLOSED, -1 };
}
int deletedRows{};
auto errorCode = store->Delete(deletedRows, predicates);
return { errorCode, deletedRows };
}
void TransactionImpl::AddResultSet(std::weak_ptr<ResultSet> resultSet)
{
std::lock_guard lock(mutex_);
resultSets_.push_back(std::move(resultSet));
}
std::shared_ptr<ResultSet> TransactionImpl::QueryByStep(const std::string &sql, const Values &args)
{
auto store = GetStore();
if (store == nullptr) {
LOG_ERROR("transaction already close");
return nullptr;
}
auto resultSet = store->QueryByStep(sql, args);
if (resultSet != nullptr) {
AddResultSet(resultSet);
}
return resultSet;
}
std::shared_ptr<ResultSet> TransactionImpl::QueryByStep(const AbsRdbPredicates &predicates, const Fields &columns)
{
auto store = GetStore();
if (store == nullptr) {
LOG_ERROR("transaction already close");
return nullptr;
}
auto resultSet = store->QueryByStep(predicates, columns);
if (resultSet != nullptr) {
AddResultSet(resultSet);
}
return resultSet;
}
std::pair<int32_t, ValueObject> TransactionImpl::Execute(const std::string &sql, const Values &args)
{
auto store = GetStore();
if (store == nullptr) {
LOG_ERROR("transaction already close");
return { E_ALREADY_CLOSED, ValueObject() };
}
return store->Execute(sql, args);
}
}

View File

@ -368,6 +368,12 @@ bool ValueObject::operator<(const ValueObject &rhs) const
case TYPE_BLOB:
result = Blob(*this) < Blob(rhs);
break;
case TYPE_ASSET:
result = Asset(*this) < Asset(rhs);
break;
case TYPE_ASSETS:
result = Assets(*this) < Assets(rhs);
break;
case TYPE_VECS:
result = FloatVector(*this) < FloatVector(rhs);
break;
@ -379,5 +385,15 @@ bool ValueObject::operator<(const ValueObject &rhs) const
}
return result;
}
bool ValueObject::operator==(const ValueObject &rhs) const
{
return !(rhs < *this || *this < rhs);
}
bool ValueObject::operator!=(const ValueObject &rhs) const
{
return (rhs < *this || *this < rhs);
}
} // namespace NativeRdb
} // namespace OHOS

View File

@ -29,6 +29,7 @@ base_sources = [
"${relational_store_native_path}/rdb/src/rdb_security_manager.cpp",
"${relational_store_native_path}/rdb/src/rdb_sql_statistic.cpp",
"${relational_store_native_path}/rdb/src/rdb_sql_utils.cpp",
"${relational_store_native_path}/rdb/src/rdb_store.cpp",
"${relational_store_native_path}/rdb/src/rdb_store_config.cpp",
"${relational_store_native_path}/rdb/src/rdb_store_impl.cpp",
"${relational_store_native_path}/rdb/src/rdb_store_manager.cpp",
@ -39,6 +40,9 @@ base_sources = [
"${relational_store_native_path}/rdb/src/sqlite_utils.cpp",
"${relational_store_native_path}/rdb/src/step_result_set.cpp",
"${relational_store_native_path}/rdb/src/string_utils.cpp",
"${relational_store_native_path}/rdb/src/trans_db.cpp",
"${relational_store_native_path}/rdb/src/transaction.cpp",
"${relational_store_native_path}/rdb/src/transaction_impl.cpp",
"${relational_store_native_path}/rdb/src/value_object.cpp",
"${relational_store_native_path}/rdb/src/values_bucket.cpp",
"${relational_store_native_path}/rdb/src/values_buckets.cpp",
@ -588,11 +592,9 @@ if (is_ohos && !build_ohos_sdk) {
deps += [
"${relational_store_innerapi_path}/appdatafwk:relational_common_base",
"//base/hiviewdfx/hilog/interfaces/native/innerkits:libhilog_ios",
"//commonlibrary/c_utils/base:utilsbase",
"//third_party/sqlite:sqlite_static",
]
external_deps = [ "c_utils:utils" ]
cflags_cc = [ "-std=c++17" ]
public_configs = [ ":native_rdb_public_config" ]

View File

@ -297,6 +297,11 @@ public:
API_EXPORT int Close() override;
protected:
/**
* @brief Constructor.
*/
API_EXPORT explicit AbsResultSet(bool safe);
template<typename Mtx>
class Lock {
public:
@ -344,7 +349,8 @@ protected:
int rowPos_ = INIT_POS;
bool isClosed_ = false;
int rowCount_ = NO_COUNT;
int32_t lastErr_;
int32_t lastErr_ = E_OK;
private:
int InitColumnNames();

View File

@ -40,6 +40,35 @@ struct AssetValue {
std::string size;
std::string hash;
std::string path;
bool operator<(const AssetValue &ref) const
{
if (name != ref.name) {
return name < ref.name;
}
if (status != ref.status) {
return status < ref.status;
}
if (id != ref.id) {
return id < ref.id;
}
if (uri != ref.uri) {
return uri < ref.uri;
}
if (createTime != ref.createTime) {
return createTime < ref.createTime;
}
if (modifyTime != ref.modifyTime) {
return modifyTime < ref.modifyTime;
}
if (size != ref.size) {
return size < ref.size;
}
if (hash != ref.hash) {
return hash < ref.hash;
}
return path < ref.path;
}
};
}
#endif // OHOS_RELATIONAL_STORE_INNER_API_ASSET_VALUE_H

View File

@ -423,4 +423,3 @@ static constexpr int E_INNER_WARNING = (E_BASE + 0x4c);
} // namespace OHOS
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,183 @@
/*
* Copyright (c) 2024 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef NATIVE_RDB_TRANSACTION_H
#define NATIVE_RDB_TRANSACTION_H
#include <tuple>
#include <utility>
#include <vector>
#include <functional>
#include "abs_rdb_predicates.h"
#include "result_set.h"
#include "rdb_common.h"
#include "rdb_errno.h"
#include "rdb_types.h"
#include "rdb_visibility.h"
#include "values_bucket.h"
#include "values_buckets.h"
namespace OHOS::NativeRdb {
class Connection;
class API_EXPORT Transaction {
public:
/**
* @brief Use Fields replace std::vector<std::string> columns.
*/
using Fields = std::vector<std::string>;
/**
* @brief Use Values replace std::vector<ValueObject> args.
*/
using Values = std::vector<ValueObject>;
/**
* @brief Use Row replace ValuesBucket.
*/
using Row = ValuesBucket;
/**
* @brief Use Rows replace std::vector<Row>.
*/
using Rows = std::vector<Row>;
/**
* @brief Use Rows replace std::vector<Row>.
*/
using RefRows = ValuesBuckets;
/**
* @brief Use Resolution replace ConflictResolution.
*/
using Resolution = ConflictResolution;
static constexpr Resolution NO_ACTION = ConflictResolution::ON_CONFLICT_NONE;
enum TransactionType : int32_t {
DEFERRED,
IMMEDIATE,
EXCLUSIVE,
TRANS_BUTT,
};
using Creator = std::function<std::pair<int32_t, std::shared_ptr<Transaction>>(
int32_t type, std::shared_ptr<Connection> connection, const std::string&)>;
static std::pair<int32_t, std::shared_ptr<Transaction>> Create(
int32_t type, std::shared_ptr<Connection> connection, const std::string &name);
static int32_t RegisterCreator(Creator creator);
virtual ~Transaction() = default;
virtual int32_t Commit() = 0;
virtual int32_t Rollback() = 0;
virtual int32_t Close() = 0;
/**
* @brief Inserts a row of data into the target table.
*
* @param table Indicates the target table.
* @param row Indicates the row of data {@link ValuesBucket} to be inserted into the table.
* @param resolution Indicates the {@link ConflictResolution} to insert data into the table.
*/
virtual std::pair<int32_t, int64_t> Insert(const std::string &table, const Row &row,
Resolution resolution = NO_ACTION) = 0;
/**
* @brief Inserts a batch of data into the target table.
*
* @param table Indicates the target table.
* @param rows Indicates the rows of data {@link ValuesBucket} to be inserted into the table.
*/
virtual std::pair<int32_t, int64_t> BatchInsert(const std::string &table, const Rows &rows) = 0;
/**
* @brief Inserts a batch of data into the target table.
*
* @param table Indicates the target table.
* @param values Indicates the rows of data {@link ValuesBuckets} to be inserted into the table.
*/
virtual std::pair<int32_t, int64_t> BatchInsert(const std::string &table, const RefRows &rows) = 0;
/**
* @brief Updates data in the database based on specified conditions.
*
* @param table Indicates the target table.
* @param row Indicates the row of data to be updated in the database.
* The key-value pairs are associated with column names of the database table.
* @param whereClause Indicates the where clause.
* @param args Indicates the where arguments.
*/
virtual std::pair<int, int> Update(const std::string &table, const Row &row, const std::string &where = "",
const Values &args = {}, Resolution resolution = NO_ACTION) = 0;
/**
* @brief Updates data in the database based on a a specified instance object of AbsRdbPredicates.
*
* @param values Indicates the row of data to be updated in the database.
* The key-value pairs are associated with column names of the database table.
* @param predicates Indicates the specified update condition by the instance object of {@link AbsRdbPredicates}.
*/
virtual std::pair<int32_t, int32_t> Update(const Row &row, const AbsRdbPredicates &predicates,
Resolution resolution = NO_ACTION) = 0;
/**
* @brief Deletes data from the database based on specified conditions.
*
* @param table Indicates the target table.
* @param whereClause Indicates the where clause.
* @param args Indicates the where arguments.
*/
virtual std::pair<int32_t, int32_t> Delete(const std::string &table, const std::string &whereClause = "",
const Values &args = {}) = 0;
/**
* @brief Deletes data from the database based on a specified instance object of AbsRdbPredicates.
*
* @param predicates Indicates the specified update condition by the instance object of {@link AbsRdbPredicates}.
*/
virtual std::pair<int32_t, int32_t> Delete(const AbsRdbPredicates &predicates) = 0;
/**
* @brief Queries data in the database based on SQL statement.
*
* @param sql Indicates the SQL statement to execute.
* @param args Indicates the selection arguments.
*/
virtual std::shared_ptr<ResultSet> QueryByStep(const std::string &sql, const Values &args = {}) = 0;
/**
* @brief Queries data in the database based on specified conditions.
*
* @param predicates Indicates the specified query condition by the instance object of {@link AbsRdbPredicates}.
* @param columns Indicates the columns to query. If the value is empty array, the query applies to all columns.
*/
virtual std::shared_ptr<ResultSet> QueryByStep(const AbsRdbPredicates &predicates, const Fields &columns = {}) = 0;
/**
* @brief Executes an SQL statement that contains specified parameters and
* get two values of type int and ValueObject.
*
* @param sql Indicates the SQL statement to execute.
* @param args Indicates the {@link ValueObject} values of the parameters in the SQL statement.
*/
virtual std::pair<int32_t, ValueObject> Execute(const std::string &sql, const Values &args = {}) = 0;
private:
static inline Creator creator_;
};
}
#endif

View File

@ -1,4 +1,3 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
@ -377,6 +376,10 @@ public:
bool operator<(const ValueObject &rhs) const;
bool operator==(const ValueObject &rhs) const;
bool operator!=(const ValueObject &rhs) const;
private:
template<class T>
int Get(T &output) const;

View File

@ -1,123 +0,0 @@
/*
* Copyright (c) 2023 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef NATIVE_RDB_ABS_RESULT_SET_H
#define NATIVE_RDB_ABS_RESULT_SET_H
#include <memory>
#include <string>
#include <vector>
#include <map>
#include <mutex>
#include "result_set.h"
#include "value_object.h"
namespace OHOS {
namespace NativeRdb {
class AbsResultSet : public ResultSet {
public:
AbsResultSet();
virtual ~AbsResultSet();
int GetRowCount(int &count) override;
int GetAllColumnNames(std::vector<std::string> &columnNames) override;
int GetBlob(int columnIndex, std::vector<uint8_t> &blob) override;
int GetString(int columnIndex, std::string &value) override;
int GetInt(int columnIndex, int &value) override;
int GetLong(int columnIndex, int64_t &value) override;
int GetDouble(int columnIndex, double &value) override;
int GetAsset(int32_t col, ValueObject::Asset &value) override;
int GetAssets(int32_t col, ValueObject::Assets &value) override;
int GetFloat32Array(int32_t index, ValueObject::FloatVector &vecs) override;
int IsColumnNull(int columnIndex, bool &isNull) override;
int GetRow(RowEntity &rowEntity) override;
int GoToRow(int position) override;
int GetColumnType(int columnIndex, ColumnType &columnType) override;
int GetRowIndex(int &position) const override;
int GoTo(int offset) override;
int GoToFirstRow() override;
int GoToLastRow() override;
int GoToNextRow() override;
int GoToPreviousRow() override;
int IsAtFirstRow(bool &result) const override;
int IsAtLastRow(bool &result) override;
int IsStarted(bool &result) const override;
int IsEnded(bool &result) override;
int GetColumnCount(int &count) override;
int GetColumnIndex(const std::string &columnName, int &columnIndex) override;
int GetColumnName(int columnIndex, std::string &columnName) override;
bool IsClosed() const override;
int Close() override;
protected:
template<typename Mtx>
class Lock {
public:
Lock(bool enable = false)
{
if (enable) {
mutex_ = new Mtx();
}
};
~Lock()
{
delete mutex_;
mutex_ = nullptr;
}
void lock()
{
if (mutex_ != nullptr) {
mutex_->lock();
}
};
void unlock()
{
if (mutex_ != nullptr) {
mutex_->unlock();
}
};
private:
Mtx* mutex_ = nullptr;
};
using Mutex = Lock<std::mutex>;
virtual std::pair<int, std::vector<std::string>> GetColumnNames();
std::pair<int, bool> IsEnded();
// The default position of the result set
static const int INIT_POS = -1;
static constexpr int NO_COUNT = -1;
Mutex globalMtx_;
/*
* The value can be in the range [-1 ~ n], where -1 represents the start flag position and N represents the data end
* flag position, and [0, n-1] represents the real data index.
*/
int rowPos_ = INIT_POS;
bool isClosed_ = false;
int rowCount_ = NO_COUNT;
int32_t lastErr_;
private:
int InitColumnNames();
// Indicates whether the result set is closed
int columnCount_ = -1;
std::map<std::string, int> columnMap_;
};
} // namespace NativeRdb
} // namespace OHOS
#endif

View File

@ -1,45 +0,0 @@
/*
* Copyright (c) 2023 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef OHOS_RELATIONAL_STORE_INNER_API_ASSET_VALUE_H
#define OHOS_RELATIONAL_STORE_INNER_API_ASSET_VALUE_H
#include <string>
namespace OHOS::NativeRdb {
struct AssetValue {
enum Status : int32_t {
STATUS_UNKNOWN,
STATUS_NORMAL,
STATUS_INSERT,
STATUS_UPDATE,
STATUS_DELETE,
STATUS_ABNORMAL,
STATUS_DOWNLOADING,
STATUS_BUTT
};
static constexpr uint64_t NO_EXPIRES_TIME = 0;
uint32_t version = 0;
mutable uint32_t status = STATUS_UNKNOWN;
uint64_t expiresTime = NO_EXPIRES_TIME;
std::string id;
std::string name;
std::string uri;
std::string createTime;
std::string modifyTime;
std::string size;
std::string hash;
std::string path;
};
}
#endif // OHOS_RELATIONAL_STORE_INNER_API_ASSET_VALUE_H

View File

@ -1,47 +0,0 @@
/*
* Copyright (c) 2024 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef OHOS_DISTRIBUTED_DATA_RELATIONAL_STORE_INTERFACES_INNER_API_RDB_INCLUDE_BIG_INTEGER_H
#define OHOS_DISTRIBUTED_DATA_RELATIONAL_STORE_INTERFACES_INNER_API_RDB_INCLUDE_BIG_INTEGER_H
#include <cinttypes>
#include <unistd.h>
#include <vector>
namespace OHOS::NativeRdb {
class BigInteger final {
public:
BigInteger() = default;
~BigInteger() = default;
BigInteger(int64_t value);
BigInteger(int32_t sign, std::vector<uint64_t> &&trueForm);
BigInteger(const BigInteger &other);
BigInteger(BigInteger &&other);
BigInteger &operator=(const BigInteger &other);
BigInteger &operator=(BigInteger &&other);
bool operator==(const BigInteger &other);
bool operator<(const BigInteger &rhs);
int32_t Sign() const;
size_t Size() const;
const uint64_t *TrueForm() const;
std::vector<uint64_t> Value() const;
private:
int32_t sign_ = 0;
std::vector<uint64_t> value_;
};
}
#endif // OHOS_DISTRIBUTED_DATA_RELATIONAL_STORE_INTERFACES_INNER_API_RDB_INCLUDE_BIG_INTEGER_H

View File

@ -1,52 +0,0 @@
/*
* Copyright (c) 2023 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef NATIVE_RDB_RDB_COMMON_H
#define NATIVE_RDB_RDB_COMMON_H
#include <cstdint>
namespace OHOS {
namespace NativeRdb {
enum class ConflictResolution {
ON_CONFLICT_NONE = 0,
ON_CONFLICT_ROLLBACK,
ON_CONFLICT_ABORT,
ON_CONFLICT_FAIL,
ON_CONFLICT_IGNORE,
ON_CONFLICT_REPLACE,
};
enum RebuiltType : uint32_t {
NONE,
REBUILT,
REPAIRED,
};
enum SlaveStatus : uint32_t {
UNDEFINED,
DB_NOT_EXITS,
BACKING_UP,
BACKUP_INTERRUPT,
BACKUP_FINISHED,
};
enum ExchangeStrategy : uint32_t {
NOT_HANDLE,
BACKUP,
RESTORE,
};
}
}
#endif // NATIVE_RDB_RDB_COMMON_H

View File

@ -1,39 +0,0 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef NATIVE_RDB_RDB_HELPER_H
#define NATIVE_RDB_RDB_HELPER_H
#include <memory>
#include <mutex>
#include <string>
#include "rdb_open_callback.h"
#include "rdb_store.h"
#include "rdb_store_config.h"
namespace OHOS {
namespace NativeRdb {
class RdbHelper final {
public:
static std::shared_ptr<RdbStore> GetRdbStore(
const RdbStoreConfig &config, int version, RdbOpenCallback &openCallback, int &errCode);
static int DeleteRdbStore(const std::string &path);
static int DeleteRdbStore(const RdbStoreConfig &config);
static void ClearCache();
};
} // namespace NativeRdb
} // namespace OHOS
#endif

View File

@ -1,71 +0,0 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef NATIVE_RDB_RDB_OPEN_CALLBACK_H
#define NATIVE_RDB_RDB_OPEN_CALLBACK_H
#include "rdb_store.h"
namespace OHOS {
namespace NativeRdb {
class RdbOpenCallback {
public:
/**
* Called when the database associate whit this RdbStore is created with the first time.
* This is where the creation of tables and insert the initial data of tables should happen.
*
* param store The RdbStore object.
*/
virtual int OnCreate(RdbStore &rdbStore) = 0;
/**
* Called when the database associate whit this RdbStore needs to be upgrade.
*
* param store The RdbStore object.
* param oldVersion The old database version.
* param newVersion The new database version.
*/
virtual int OnUpgrade(RdbStore &rdbStore, int currentVersion, int targetVersion) = 0;
/**
* Called when the database associate whit this RdbStore needs to be downgrade.
*
* param store The RdbStore object.
* param oldVersion The old database version.
* param newVersion The new database version.
*/
virtual int OnDowngrade(RdbStore &rdbStore, int currentVersion, int targetVersion)
{
return 0;
}
/**
* Called when the RdbStore has been opened.
*
* param store The RdbStore object.
*/
virtual int OnOpen(RdbStore &rdbStore)
{
return 0;
}
virtual int onCorruption(std::string databaseFile)
{
return 0;
}
};
} // namespace NativeRdb
} // namespace OHOS
#endif

View File

@ -1,44 +0,0 @@
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef NATIVE_RDB_RDBPREDICATES_H
#define NATIVE_RDB_RDBPREDICATES_H
#include "abs_rdb_predicates.h"
namespace OHOS {
namespace NativeRdb {
class RdbPredicates : public AbsRdbPredicates {
public:
explicit RdbPredicates(const std::string &tableName);
~RdbPredicates() override {}
std::string GetJoinClause() const override;
RdbPredicates *CrossJoin(const std::string &tableName);
RdbPredicates *InnerJoin(const std::string &tableName);
RdbPredicates *LeftOuterJoin(const std::string &tableName);
RdbPredicates *Using(const std::vector<std::string> &fields);
RdbPredicates *On(const std::vector<std::string> &clauses);
private:
std::string ProcessJoins() const;
std::string GetGrammar(int type) const;
RdbPredicates *Join(int join, const std::string &tableName);
};
} // namespace NativeRdb
} // namespace OHOS
#endif

View File

@ -1,132 +0,0 @@
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef NATIVE_RDB_RDB_STORE_H
#define NATIVE_RDB_RDB_STORE_H
#include <memory>
#include <string>
#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 "values_buckets.h"
namespace OHOS::NativeRdb {
class RdbStore {
public:
using RdbStoreObserver = DistributedRdb::RdbStoreObserver;
using PRIKey = RdbStoreObserver::PrimaryKey;
using Date = DistributedRdb::Date;
virtual ~RdbStore() {}
virtual int Insert(int64_t &outRowId, const std::string &table, const ValuesBucket &values) = 0;
virtual int BatchInsert(int64_t &outInsertNum, const std::string &table,
const std::vector<ValuesBucket> &values) = 0;
virtual std::pair<int, int64_t> BatchInsert(const std::string &table, const ValuesBuckets &values)
{
return { E_NOT_SUPPORT, 0 };
}
virtual int Replace(int64_t &outRowId, const std::string &table, const ValuesBucket &values) = 0;
virtual int InsertWithConflictResolution(
int64_t &outRowId, const std::string &table, const ValuesBucket &values,
ConflictResolution conflictResolution = ConflictResolution::ON_CONFLICT_NONE) = 0;
virtual int Update(int &changedRows, const std::string &table, const ValuesBucket &values,
const std::string &whereClause, const std::vector<std::string> &whereArgs) = 0;
virtual int Update(int &changedRows, const std::string &table, const ValuesBucket &values,
const std::string &whereClause, const std::vector<ValueObject> &bindArgs) = 0;
virtual int UpdateWithConflictResolution(int &changedRows, const std::string &table, const ValuesBucket &values,
const std::string &whereClause, const std::vector<std::string> &whereArgs,
ConflictResolution conflictResolution) = 0;
virtual int UpdateWithConflictResolution(int &changedRows, const std::string &table, const ValuesBucket &values,
const std::string &whereClause, const std::vector<ValueObject> &bindArgs,
ConflictResolution conflictResolution) = 0;
virtual int Delete(int &deletedRows, const std::string &table, const std::string &whereClause,
const std::vector<std::string> &whereArgs) = 0;
virtual int Delete(int &deletedRows, const std::string &table, const std::string &whereClause,
const std::vector<ValueObject> &bindArgs) = 0;
virtual std::shared_ptr<ResultSet> QueryByStep(const std::string &sql,
const std::vector<std::string> &sqlArgs) = 0;
virtual std::shared_ptr<ResultSet> QueryByStep(const std::string &sql, const std::vector<ValueObject> &args) = 0;
virtual std::shared_ptr<ResultSet> QueryByStep(
const AbsRdbPredicates &predicates, const std::vector<std::string> &columns) = 0;
virtual int ExecuteSql(const std::string &sql, const std::vector<ValueObject> &bindArgs = {}) = 0;
virtual std::pair<int32_t, ValueObject> Execute(const std::string &sql,
const std::vector<ValueObject> &bindArgs = {}, int64_t txId = 0) = 0;
virtual int ExecuteAndGetLong(int64_t &outValue, const std::string &sql,
const std::vector<ValueObject> &bindArgs = {}) = 0;
virtual int ExecuteAndGetString(std::string &outValue, const std::string &sql,
const std::vector<ValueObject> &bindArgs = {}) = 0;
virtual int ExecuteForLastInsertedRowId(int64_t &outValue, const std::string &sql,
const std::vector<ValueObject> &bindArgs = {}) = 0;
virtual int ExecuteForChangedRowCount(int64_t &outValue, const std::string &sql,
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)
{
return E_OK;
}
virtual int Count(int64_t &outValue, const AbsRdbPredicates &predicates) = 0;
virtual std::shared_ptr<ResultSet> Query(
const AbsRdbPredicates &predicates, const std::vector<std::string> &columns) = 0;
virtual int Update(int &changedRows, const ValuesBucket &values, const AbsRdbPredicates &predicates) = 0;
virtual int Delete(int &deletedRows, const AbsRdbPredicates &predicates) = 0;
virtual int GetVersion(int &version) = 0;
virtual int SetVersion(int version) = 0;
virtual int BeginTransaction() = 0;
virtual std::pair<int, int64_t> BeginTrans() = 0;
virtual int RollBack() = 0;
virtual int RollBack(int64_t trxId) = 0;
virtual int Commit() = 0;
virtual int Commit(int64_t trxId) = 0;
virtual bool IsInTransaction() = 0;
virtual std::string GetPath() = 0;
virtual bool IsHoldingConnection() = 0;
virtual bool IsOpen() const = 0;
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;
virtual int GetRebuilt(RebuiltType &rebuilt) = 0;
virtual int32_t GetDbType() const
{
return DB_SQLITE;
}
virtual int InterruptBackup()
{
return E_OK;
}
virtual bool IsSlaveDiffFromMaster() const
{
return false;
}
virtual int32_t GetBackupStatus() const
{
return SlaveStatus::UNDEFINED;
}
};
} // namespace OHOS::NativeRdb
#endif

View File

@ -1,58 +0,0 @@
/*
* Copyright (c) 2023 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef NATIVE_RDB_RESULT_SET_H
#define NATIVE_RDB_RESULT_SET_H
#include <string>
#include <vector>
#include <map>
#include "remote_result_set.h"
#include "value_object.h"
namespace OHOS {
namespace NativeRdb {
struct RowEntity {
public:
void Put(const std::string &name, int32_t index, ValueObject &&value);
ValueObject Get(const std::string &name) const;
ValueObject Get(int index) const;
const std::map<std::string, ValueObject> &Get() const;
std::map<std::string, ValueObject> Steal();
void Clear(int32_t size);
private:
std::map<std::string, ValueObject> values_;
std::vector<decltype(values_)::iterator> indexs_;
};
class ResultSet : public RemoteResultSet {
public:
virtual ~ResultSet() {}
virtual int GetAsset(int32_t col, ValueObject::Asset &value) = 0;
virtual int GetAssets(int32_t col, ValueObject::Assets &value) = 0;
virtual int GetFloat32Array(int32_t index, ValueObject::FloatVector &vecs) = 0;
virtual int Get(int32_t col, ValueObject &value) = 0;
/**
* @brief Gets the entire row of data for the current row from the result set.
*/
virtual int GetRow(RowEntity &rowEntity) = 0;
virtual int GetSize(int columnIndex, size_t &size) = 0;
};
} // namespace NativeRdb
} // namespace OHOS
#endif

View File

@ -1,359 +0,0 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef NATIVE_RDB_VALUE_OBJECT_H
#define NATIVE_RDB_VALUE_OBJECT_H
#include <string>
#include <variant>
#include <vector>
#include "big_integer.h"
#include "asset_value.h"
namespace OHOS {
namespace NativeRdb {
/**
* The ValueObject class of RDB.
*/
class ValueObject {
public:
/**
* @brief Use Type replace std::variant.
*/
using Nil = std::monostate;
using Blob = std::vector<uint8_t>;
using Asset = AssetValue;
using Assets = std::vector<Asset>;
using BigInt = BigInteger;
using FloatVector = std::vector<float>;
using Type = std::variant<Nil, int64_t, double, std::string, bool, Blob, Asset, Assets, FloatVector, BigInt>;
template<typename Tp, typename... Types>
struct index_of : std::integral_constant<size_t, 0> {};
template<typename Tp, typename... Types>
inline static constexpr size_t index_of_v = index_of<Tp, Types...>::value;
template<typename Tp, typename First, typename... Rest>
struct index_of<Tp, First, Rest...>
: std::integral_constant<size_t, std::is_same_v<Tp, First> ? 0 : index_of_v<Tp, Rest...> + 1> {};
template<typename... Types>
struct variant_size_of {
static constexpr size_t value = sizeof...(Types);
};
template<typename T, typename... Types>
struct variant_index_of {
static constexpr size_t value = index_of_v<T, Types...>;
};
template<typename... Types>
static variant_size_of<Types...> variant_size_test(const std::variant<Types...> &);
template<typename T, typename... Types>
static variant_index_of<T, Types...> variant_index_test(const T &, const std::variant<Types...> &);
template<typename T>
inline constexpr static int32_t TYPE_INDEX =
decltype(variant_index_test(std::declval<T>(), std::declval<Type>()))::value;
inline constexpr static int32_t TYPE_MAX = decltype(variant_size_test(std::declval<Type>()))::value;
/**
* @brief Indicates the ValueObject {@link ValueObject} type.
* */
enum TypeId : int32_t {
/** Indicates the ValueObject type is NULL.*/
TYPE_NULL = TYPE_INDEX<Nil>,
/** Indicates the ValueObject type is int.*/
TYPE_INT = TYPE_INDEX<int64_t>,
/** Indicates the ValueObject type is double.*/
TYPE_DOUBLE = TYPE_INDEX<double>,
/** Indicates the ValueObject type is string.*/
TYPE_STRING = TYPE_INDEX<std::string>,
/** Indicates the ValueObject type is bool.*/
TYPE_BOOL = TYPE_INDEX<bool>,
/** Indicates the ValueObject type is blob.*/
TYPE_BLOB = TYPE_INDEX<Blob>,
/** Indicates the ValueObject type is asset.*/
TYPE_ASSET = TYPE_INDEX<Asset>,
/** Indicates the ValueObject type is assets.*/
TYPE_ASSETS = TYPE_INDEX<Assets>,
/** Indicates the ValueObject type is vecs.*/
TYPE_VECS = TYPE_INDEX<FloatVector>,
/** Indicates the ValueObject type is bigint.*/
TYPE_BIGINT = TYPE_INDEX<BigInt>,
/** the BUTT.*/
TYPE_BUTT = TYPE_MAX
};
Type value;
/**
* @brief convert a std::variant input to another std::variant output with different (..._Types)
*/
template<typename T>
static inline std::enable_if_t<(TYPE_INDEX<T>) < TYPE_MAX, const char *> DeclType()
{
return DECLARE_TYPES[TYPE_INDEX<T>];
}
/**
* @brief Constructor.
*/
ValueObject();
/**
* @brief Destructor.
*/
~ValueObject();
/**
* @brief Constructor.
*
* A parameterized constructor used to create a ValueObject instance.
*/
ValueObject(Type val) noexcept;
/**
* @brief Move constructor.
*/
ValueObject(ValueObject &&val) noexcept;
/**
* @brief Copy constructor.
*/
ValueObject(const ValueObject &val);
/**
* @brief Constructor.
*
* This constructor is used to convert the int input parameter to a value of type ValueObject.
*
* @param val Indicates an int input parameter.
*/
ValueObject(int32_t val);
/**
* @brief Constructor.
*
* This constructor is used to convert the int64_t input parameter to a value of type ValueObject.
*
* @param val Indicates an int64_t input parameter.
*/
ValueObject(int64_t val);
/**
* @brief Constructor.
*
* This constructor is used to convert the double input parameter to a value of type ValueObject.
*
* @param val Indicates an double input parameter.
*/
ValueObject(double val);
/**
* @brief Constructor.
*
* This constructor is used to convert the bool input parameter to a value of type ValueObject.
*
* @param val Indicates an bool input parameter.
*/
ValueObject(bool val);
/**
* @brief Constructor.
*
* This constructor is used to convert the string input parameter to a value of type ValueObject.
*
* @param val Indicates an string input parameter.
*/
ValueObject(std::string val);
/**
* @brief Constructor.
*
* This constructor is used to convert the const char * input parameter to a value of type ValueObject.
*
* @param val Indicates an const char * input parameter.
*/
ValueObject(const char *val);
/**
* @brief Constructor.
*
* This constructor is used to convert the vector<uint8_t> input parameter to a value of type ValueObject.
*
* @param val Indicates an vector<uint8_t> input parameter.
*/
ValueObject(const std::vector<uint8_t> &blob);
/**
* @brief Constructor.
*
* This constructor is used to convert the Asset input parameter to a value of type ValueObject.
*
* @param val Indicates an Asset input parameter.
*/
ValueObject(Asset val);
/**
* @brief Constructor.
*
* This constructor is used to convert the Assets input parameter to a value of type ValueObject.
*
* @param val Indicates an Assets input parameter.
*/
ValueObject(Assets val);
/**
* @brief Constructor.
*
* This constructor is used to convert the Assets input parameter to a value of type ValueObject.
*
* @param val Indicates an Assets input parameter.
*/
ValueObject(BigInt val);
/**
* @brief Constructor.
* This constructor is used to convert the FloatVector input parameter to a value of type ValueObject.
*
* @param val Indicates an FloatVector input parameter.
*/
ValueObject(FloatVector val);
/**
* @brief Move assignment operator overloaded function.
*/
ValueObject &operator=(ValueObject &&valueObject) noexcept;
/**
* @brief Copy assignment operator overloaded function.
*/
ValueObject &operator=(const ValueObject &valueObject);
/**
* @brief Obtains the type in this {@code ValueObject} object.
*/
TypeId GetType() const;
/**
* @brief Obtains the int value in this {@code ValueObject} object.
*/
int GetInt(int &val) const;
/**
* @brief Obtains the long value in this {@code ValueObject} object.
*/
int GetLong(int64_t &val) const;
/**
* @brief Obtains the double value in this {@code ValueObject} object.
*/
int GetDouble(double &val) const;
/**
* @brief Obtains the bool value in this {@code ValueObject} object.
*/
int GetBool(bool &val) const;
/**
* @brief Obtains the string value in this {@code ValueObject} object.
*/
int GetString(std::string &val) const;
/**
* @brief Obtains the vector<uint8_t> value in this {@code ValueObject} object.
*/
int GetBlob(std::vector<uint8_t> &val) const;
/**
* @brief Obtains the vector<uint8_t> value in this {@code ValueObject} object.
*/
int GetAsset(Asset &val) const;
/**
* @brief Obtains the vector<uint8_t> value in this {@code ValueObject} object.
*/
int GetAssets(Assets &val) const;
/**
* @brief Obtains the vector<float> value in this {@code ValueObject} object.
*/
int GetVecs(FloatVector &val) const;
operator int() const;
operator int64_t() const;
operator double() const;
operator bool() const;
operator std::string() const;
operator Blob() const;
operator Asset() const;
operator Assets() const;
/**
* @brief Type conversion function.
*
* @return Returns the vector<float> type ValueObject.
*/
operator FloatVector() const;
/**
* @brief Type conversion function.
*
* @return Returns the BigInt type ValueObject.
*/
operator BigInt() const;
/**
* @brief Type conversion function.
*
* @return Returns the Type type ValueObject.
*/
operator Type() const
{
return value;
}
bool operator<(const ValueObject &rhs) const;
private:
template<class T>
int Get(T &output) const;
static constexpr const char *DECLARE_TYPES[TypeId::TYPE_BUTT] = {
/** Indicates the ValueObject type is NULL.*/
"",
/** Indicates the ValueObject type is int.*/
"INT",
/** Indicates the ValueObject type is double.*/
"REAL",
/** Indicates the ValueObject type is string.*/
"TEXT",
/** Indicates the ValueObject type is bool.*/
"BOOL",
/** Indicates the ValueObject type is blob.*/
"BLOB",
/** Indicates the ValueObject type is asset.*/
"ASSET",
/** Indicates the ValueObject type is assets.*/
"ASSETS",
/** Indicates the ValueObject type is vecs.*/
"FLOATVECTOR",
/** Indicates the ValueObject type is bigint.*/
"UNLIMITED INT"
};
};
using ValueObjectType = ValueObject::TypeId;
} // namespace NativeRdb
} // namespace OHOS
#endif

View File

@ -1,51 +0,0 @@
/*
* Copyright (c) 2024 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef NATIVE_RDB_VALUES_BUCKETS_H
#define NATIVE_RDB_VALUES_BUCKETS_H
#include <map>
#include <set>
#include <memory>
#include "value_object.h"
#include "values_bucket.h"
namespace OHOS {
namespace NativeRdb {
class ValuesBuckets {
public:
using FieldsType = std::shared_ptr<std::set<std::string>>;
using ValuesType = std::shared_ptr<std::set<ValueObject>>;
using FieldType = std::reference_wrapper<const std::string>;
using ValueType = std::reference_wrapper<ValueObject>;
using BucketType = std::map<FieldType, ValueType, std::less<std::string>>;
ValuesBuckets();
size_t RowSize() const;
std::pair<FieldsType, ValuesType> GetFieldsAndValues() const;
void Put(const ValuesBucket &bucket);
std::pair<int, ValueType> Get(size_t row, const FieldType &field) const;
private:
FieldsType fields_;
ValuesType values_;
std::vector<BucketType> buckets_;
};
} // namespace NativeRdb
} // namespace OHOS
#endif

View File

@ -51,5 +51,4 @@ DistributedDB::DBStatus UnLock(
const std::string &tableName, const std::vector<std::vector<uint8_t>> &hashKey, sqlite3 *db);
DistributedDB::DBStatus DropLogicDeletedData(sqlite3* db,
const std::string& tableName, uint64_t cursor);
#endif //RELATIONAL_STORE_RELATIONAL_STORE_CLIENT_H

View File

@ -119,6 +119,7 @@ describe('rdbStoreQueryByCursorTest', function () {
});
done();
})
/**
* @tc.name query with cursor
* @tc.number SUB_DDM_AppDataFWK_JSRDB_QUERY_WITH_CURSOR_0002

View File

@ -270,6 +270,7 @@ describe('rdbStoreResultSetGetRowTest', function () {
expect(false).assertEqual(resultSet.goToLastRow());
console.log(TAG + "************* rdbStoreInsertUndefinedValueTest0008 end *************");
})
/**
* @tc.name rdb store resultSet getRow test
* @tc.number rdbStoreResultSetGoToLastRow0009

View File

@ -0,0 +1,945 @@
/*
* 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_TRANSACTION_JSKITS_TEST]"
const CREATE_TABLE_TEST = "CREATE TABLE IF NOT EXISTS test (" + "id INTEGER PRIMARY KEY, " +
"name TEXT NOT NULL, " + "age INTEGER, " + "salary REAL, " + "blobType BLOB)";
const STORE_CONFIG = {
name: "TransactionTest.db",
securityLevel: data_relationalStore.SecurityLevel.S3,
}
var rdbStore = undefined;
describe('rdbStoreTransactionJsunitTest', function () {
beforeAll(async function () {
console.info(TAG + 'beforeAll')
rdbStore = await data_relationalStore.getRdbStore(context, STORE_CONFIG);
await rdbStore.executeSql(CREATE_TABLE_TEST, null);
})
beforeEach(async function () {
console.info(TAG + 'beforeEach')
})
afterEach(async function () {
console.info(TAG + 'afterEach')
await rdbStore.executeSql("DELETE FROM test");
})
afterAll(async function () {
console.info(TAG + 'afterAll')
rdbStore = null
await data_relationalStore.deleteRdbStore(context, "TransactionTest.db");
})
console.log(TAG + "*************Unit Test Begin*************");
it('testRdbTransInsert0001', 0, async (done) => {
console.log(TAG + "************* testRdbTransInsert0001 start *************");
try {
const u8 = new Uint8Array([1, 2, 3]);
const rdbTrans = await rdbStore.createTransaction({
transactionType: data_relationalStore.TransactionType.DEFERRED
});
const valueBucket = {
"name": "lisi",
"age": 18,
"salary": 100.5,
"blobType": u8,
};
await rdbTrans.insert("test", valueBucket);
await rdbTrans.commit();
let predicates = new data_relationalStore.RdbPredicates("test");
let resultSet = await rdbStore.query(predicates);
console.log(TAG + "testRdbTransInsert0001 result count " + resultSet.rowCount);
expect(1).assertEqual(resultSet.rowCount);
resultSet.close();
} catch (e) {
console.log(TAG + e);
expect(null).assertFail();
console.log(TAG + "testRdbTransInsert0001 failed");
}
console.log(TAG + "************* testRdbTransInsert0001 end *************");
done();
})
it('testRdbTransInsert0002', 0, async (done) => {
console.log(TAG + "************* testRdbTransInsert0002 start *************");
try {
const u8 = new Uint8Array([1, 2, 3]);
const rdbTrans = await rdbStore.createTransaction({
transactionType: data_relationalStore.TransactionType.EXCLUSIVE
});
const valueBucket = {
"name": "lisi",
"age": 18,
"salary": 100.5,
"blobType": u8,
};
await rdbTrans.insert("test", valueBucket);
await rdbTrans.commit();
let predicates = new data_relationalStore.RdbPredicates("test");
let resultSet = await rdbStore.query(predicates);
console.log(TAG + "testRdbTransInsert0002 result count " + resultSet.rowCount);
expect(1).assertEqual(resultSet.rowCount);
resultSet.close();
} catch (e) {
console.log(TAG + e);
expect(null).assertFail();
console.log(TAG + "testRdbTransInsert0002 failed");
}
console.log(TAG + "************* testRdbTransInsert0002 end *************");
done();
})
it('testRdbTransInsert0003', 0, async (done) => {
console.log(TAG + "************* testRdbTransInsert0003 start *************");
try {
const u8 = new Uint8Array([1, 2, 3]);
const rdbTrans = await rdbStore.createTransaction({
transactionType: data_relationalStore.TransactionType.IMMEDIATE
});
const valueBucket = {
"name": "lisi",
"age": 18,
"salary": 100.5,
"blobType": u8,
};
await rdbTrans.insert("test", valueBucket);
await rdbTrans.commit();
let predicates = new data_relationalStore.RdbPredicates("test");
let resultSet = await rdbStore.query(predicates);
console.log(TAG + "testRdbTransInsert0003 result count " + resultSet.rowCount);
expect(1).assertEqual(resultSet.rowCount);
resultSet.close();
} catch (e) {
console.log(TAG + e);
expect(null).assertFail();
console.log(TAG + "testRdbTransInsert0003 failed");
}
console.log(TAG + "************* testRdbTransInsert0003 end *************");
done();
})
it('testRdbTransInsert0011', 0, async (done) => {
console.log(TAG + "************* testRdbTransInsert0011 start *************");
try {
const u8 = new Uint8Array([1, 2, 3]);
const rdbTrans = await rdbStore.createTransaction({
transactionType: data_relationalStore.TransactionType.DEFERRED
});
const valueBucket = {
"name": "lisi",
"age": 18,
"salary": 100.5,
"blobType": u8,
};
await rdbTrans.insert("test", valueBucket);
await rdbTrans.rollback();
let predicates = new data_relationalStore.RdbPredicates("test");
let resultSet = await rdbStore.query(predicates);
console.log(TAG + "testRdbTransInsert0011 result count " + resultSet.rowCount);
expect(0).assertEqual(resultSet.rowCount);
resultSet.close();
} catch (e) {
console.log(TAG + e);
expect(null).assertFail();
console.log(TAG + "testRdbTransInsert0011 failed");
}
console.log(TAG + "************* testRdbTransInsert0011 end *************");
done();
})
it('testRdbTransInsert0012', 0, async (done) => {
console.log(TAG + "************* testRdbTransInsert0012 start *************");
try {
const u8 = new Uint8Array([1, 2, 3]);
const rdbTrans = await rdbStore.createTransaction({
transactionType: data_relationalStore.TransactionType.EXCLUSIVE
});
const valueBucket = {
"name": "lisi",
"age": 18,
"salary": 100.5,
"blobType": u8,
};
await rdbTrans.insert("test", valueBucket);
await rdbTrans.rollback();
let predicates = new data_relationalStore.RdbPredicates("test");
let resultSet = await rdbStore.query(predicates);
console.log(TAG + "testRdbTransInsert0012 result count " + resultSet.rowCount);
expect(0).assertEqual(resultSet.rowCount);
resultSet.close();
} catch (e) {
console.log(TAG + e);
expect(null).assertFail();
console.log(TAG + "testRdbTransInsert0012 failed");
}
console.log(TAG + "************* testRdbTransInsert0012 end *************");
done();
})
it('testRdbTransInsert0013', 0, async (done) => {
console.log(TAG + "************* testRdbTransInsert0013 start *************");
try {
const u8 = new Uint8Array([1, 2, 3]);
const rdbTrans = await rdbStore.createTransaction({
transactionType: data_relationalStore.TransactionType.IMMEDIATE
});
const valueBucket = {
"name": "lisi",
"age": 18,
"salary": 100.5,
"blobType": u8,
};
await rdbTrans.insert("test", valueBucket);
await rdbTrans.rollback();
let predicates = new data_relationalStore.RdbPredicates("test");
let resultSet = await rdbStore.query(predicates);
console.log(TAG + "testRdbTransInsert0013 result count " + resultSet.rowCount);
expect(0).assertEqual(resultSet.rowCount);
resultSet.close();
} catch (e) {
console.log(TAG + e);
expect(null).assertFail();
console.log(TAG + "testRdbTransInsert0013 failed");
}
console.log(TAG + "************* testRdbTransInsert0013 end *************");
done();
})
it('testRdbTransInsertSync0001', 0, async (done) => {
console.log(TAG + "************* testRdbTransInsertSync0001 start *************");
try {
const u8 = new Uint8Array([1, 2, 3]);
const rdbTrans = await rdbStore.createTransaction({
transactionType: data_relationalStore.TransactionType.DEFERRED
});
const valueBucket = {
"name": "lisi",
"age": 18,
"salary": 100.5,
"blobType": u8,
};
const rowId = rdbTrans.insertSync("test", valueBucket);
expect(1).assertEqual(rowId);
await rdbTrans.commit();
let predicates = new data_relationalStore.RdbPredicates("test");
let resultSet = await rdbStore.query(predicates);
console.log(TAG + "testRdbTransInsertSync0001 result count " + resultSet.rowCount);
expect(1).assertEqual(resultSet.rowCount);
resultSet.close();
} catch (e) {
console.log(TAG + e);
expect(null).assertFail();
console.log(TAG + "testRdbTransInsertSync0001 failed");
}
console.log(TAG + "************* testRdbTransInsertSync0001 end *************");
done();
})
it('testRdbTransInsertSync0002', 0, async (done) => {
console.log(TAG + "************* testRdbTransInsertSync0002 start *************");
try {
const u8 = new Uint8Array([1, 2, 3]);
const rdbTrans = await rdbStore.createTransaction({
transactionType: data_relationalStore.TransactionType.EXCLUSIVE
});
const valueBucket = {
"name": "lisi",
"age": 18,
"salary": 100.5,
"blobType": u8,
};
const rowId = rdbTrans.insertSync("test", valueBucket);
expect(1).assertEqual(rowId);
await rdbTrans.commit();
let predicates = new data_relationalStore.RdbPredicates("test");
let resultSet = await rdbStore.query(predicates);
console.log(TAG + "testRdbTransInsertSync0002 result count " + resultSet.rowCount);
expect(1).assertEqual(resultSet.rowCount);
resultSet.close();
} catch (e) {
console.log(TAG + e);
expect(null).assertFail();
console.log(TAG + "testRdbTransInsertSync0002 failed");
}
console.log(TAG + "************* testRdbTransInsertSync0002 end *************");
done();
})
it('testRdbTransInsertSync0003', 0, async (done) => {
console.log(TAG + "************* testRdbTransInsertSync0003 start *************");
try {
const u8 = new Uint8Array([1, 2, 3]);
const rdbTrans = await rdbStore.createTransaction({
transactionType: data_relationalStore.TransactionType.IMMEDIATE
});
const valueBucket = {
"name": "lisi",
"age": 18,
"salary": 100.5,
"blobType": u8,
};
const rowId = rdbTrans.insertSync("test", valueBucket);
expect(1).assertEqual(rowId);
await rdbTrans.commit();
let predicates = new data_relationalStore.RdbPredicates("test");
let resultSet = await rdbStore.query(predicates);
console.log(TAG + "testRdbTransInsertSync0003 result count " + resultSet.rowCount);
expect(1).assertEqual(resultSet.rowCount);
resultSet.close();
} catch (e) {
console.log(TAG + e);
expect(null).assertFail();
console.log(TAG + "testRdbTransInsertSync0003 failed");
}
console.log(TAG + "************* testRdbTransInsertSync0003 end *************");
done();
})
it('testRdbTransInsertSync0011', 0, async (done) => {
console.log(TAG + "************* testRdbTransInsertSync0011 start *************");
try {
const u8 = new Uint8Array([1, 2, 3]);
const rdbTrans = await rdbStore.createTransaction({
transactionType: data_relationalStore.TransactionType.DEFERRED
});
const valueBucket = {
"name": "lisi",
"age": 18,
"salary": 100.5,
"blobType": u8,
};
const rowId = rdbTrans.insertSync("test", valueBucket);
expect(1).assertEqual(rowId);
await rdbTrans.rollback();
let predicates = new data_relationalStore.RdbPredicates("test");
let resultSet = await rdbStore.query(predicates);
console.log(TAG + "testRdbTransInsertSync0011 result count " + resultSet.rowCount);
expect(0).assertEqual(resultSet.rowCount);
resultSet.close();
} catch (e) {
console.log(TAG + e);
expect(null).assertFail();
console.log(TAG + "testRdbTransInsertSync0011 failed");
}
console.log(TAG + "************* testRdbTransInsertSync0011 end *************");
done();
})
it('testRdbTransInsertSync0012', 0, async (done) => {
console.log(TAG + "************* testRdbTransInsertSync0012 start *************");
try {
const u8 = new Uint8Array([1, 2, 3]);
const rdbTrans = await rdbStore.createTransaction({
transactionType: data_relationalStore.TransactionType.EXCLUSIVE
});
const valueBucket = {
"name": "lisi",
"age": 18,
"salary": 100.5,
"blobType": u8,
};
const rowId = rdbTrans.insertSync("test", valueBucket);
expect(1).assertEqual(rowId);
await rdbTrans.rollback();
let predicates = new data_relationalStore.RdbPredicates("test");
let resultSet = await rdbStore.query(predicates);
console.log(TAG + "testRdbTransInsertSync0012 result count " + resultSet.rowCount);
expect(0).assertEqual(resultSet.rowCount);
resultSet.close();
} catch (e) {
console.log(TAG + e);
expect(null).assertFail();
console.log(TAG + "testRdbTransInsertSync0012 failed");
}
console.log(TAG + "************* testRdbTransInsertSync0012 end *************");
done();
})
it('testRdbTransInsertSync0013', 0, async (done) => {
console.log(TAG + "************* testRdbTransInsertSync0013 start *************");
try {
const u8 = new Uint8Array([1, 2, 3]);
const rdbTrans = await rdbStore.createTransaction({
transactionType: data_relationalStore.TransactionType.IMMEDIATE
});
const valueBucket = {
"name": "lisi",
"age": 18,
"salary": 100.5,
"blobType": u8,
};
const rowId = rdbTrans.insertSync("test", valueBucket);
expect(1).assertEqual(rowId);
await rdbTrans.rollback();
let predicates = new data_relationalStore.RdbPredicates("test");
let resultSet = await rdbStore.query(predicates);
console.log(TAG + "testRdbTransInsertSync0013 result count " + resultSet.rowCount);
expect(0).assertEqual(resultSet.rowCount);
resultSet.close();
} catch (e) {
console.log(TAG + e);
expect(null).assertFail();
console.log(TAG + "testRdbTransInsertSync0013 failed");
}
console.log(TAG + "************* testRdbTransInsertSync0013 end *************");
done();
})
it('testRdbTransBatchInsert0001', 0, async (done) => {
console.log(TAG + "************* testRdbTransBatchInsert0001 start *************");
try {
const u8 = new Uint8Array([1, 2, 3]);
const rdbTrans = await rdbStore.createTransaction({
transactionType: data_relationalStore.TransactionType.DEFERRED
});
const valueBuckets = new Array(100).fill(0).map(() => {
const valueBucket = {
"name": "lisi",
"age": 18,
"salary": 100.5,
"blobType": u8,
};
return valueBucket;
})
const rowCount = await rdbTrans.batchInsert("test", valueBuckets);
expect(rowCount).assertEqual(100);
await rdbTrans.commit();
let predicates = new data_relationalStore.RdbPredicates("test");
let resultSet = await rdbStore.query(predicates);
console.log(TAG + "testRdbTransBatchInsert0001 result count " + resultSet.rowCount);
expect(100).assertEqual(resultSet.rowCount);
resultSet.close();
} catch (e) {
console.log(TAG + e);
expect(null).assertFail();
console.log(TAG + "testRdbTransBatchInsert0001 failed");
}
console.log(TAG + "************* testRdbTransBatchInsert0001 end *************");
done();
})
it('testRdbTransBatchInsert0002', 0, async (done) => {
console.log(TAG + "************* testRdbTransBatchInsert0002 start *************");
try {
const u8 = new Uint8Array([1, 2, 3]);
const rdbTrans = await rdbStore.createTransaction({
transactionType: data_relationalStore.TransactionType.EXCLUSIVE
});
const valueBuckets = new Array(100).fill(0).map(() => {
const valueBucket = {
"name": "lisi",
"age": 18,
"salary": 100.5,
"blobType": u8,
};
return valueBucket;
})
const rowCount = await rdbTrans.batchInsert("test", valueBuckets);
expect(rowCount).assertEqual(100);
await rdbTrans.commit();
let predicates = new data_relationalStore.RdbPredicates("test");
let resultSet = await rdbStore.query(predicates);
console.log(TAG + "testRdbTransBatchInsert0002 result count " + resultSet.rowCount);
expect(100).assertEqual(resultSet.rowCount);
resultSet.close();
} catch (e) {
console.log(TAG + e);
expect(null).assertFail();
console.log(TAG + "testRdbTransBatchInsert0002 failed");
}
console.log(TAG + "************* testRdbTransBatchInsert0002 end *************");
done();
})
it('testRdbTransBatchInsert0003', 0, async (done) => {
console.log(TAG + "************* testRdbTransBatchInsert0003 start *************");
try {
const u8 = new Uint8Array([1, 2, 3]);
const rdbTrans = await rdbStore.createTransaction({
transactionType: data_relationalStore.TransactionType.IMMEDIATE
});
const valueBuckets = new Array(100).fill(0).map(() => {
const valueBucket = {
"name": "lisi",
"age": 18,
"salary": 100.5,
"blobType": u8,
};
return valueBucket;
})
const rowCount = await rdbTrans.batchInsert("test", valueBuckets);
expect(rowCount).assertEqual(100);
await rdbTrans.commit();
let predicates = new data_relationalStore.RdbPredicates("test");
let resultSet = await rdbStore.query(predicates);
console.log(TAG + "testRdbTransBatchInsert0003 result count " + resultSet.rowCount);
expect(100).assertEqual(resultSet.rowCount);
resultSet.close();
} catch (e) {
console.log(TAG + e);
expect(null).assertFail();
console.log(TAG + "testRdbTransBatchInsert0003 failed");
}
console.log(TAG + "************* testRdbTransBatchInsert0003 end *************");
done();
})
it('testRdbTransBatchInsert0011', 0, async (done) => {
console.log(TAG + "************* testRdbTransBatchInsert0011 start *************");
try {
const u8 = new Uint8Array([1, 2, 3]);
const rdbTrans = await rdbStore.createTransaction({
transactionType: data_relationalStore.TransactionType.DEFERRED
});
const valueBuckets = new Array(100).fill(0).map(() => {
const valueBucket = {
"name": "lisi",
"age": 18,
"salary": 100.5,
"blobType": u8,
};
return valueBucket;
})
const rowCount = await rdbTrans.batchInsert("test", valueBuckets);
expect(rowCount).assertEqual(100);
await rdbTrans.rollback();
let predicates = new data_relationalStore.RdbPredicates("test");
let resultSet = await rdbStore.query(predicates);
console.log(TAG + "testRdbTransBatchInsert0011 result count " + resultSet.rowCount);
expect(0).assertEqual(resultSet.rowCount);
resultSet.close();
} catch (e) {
console.log(TAG + e);
expect(null).assertFail();
console.log(TAG + "testRdbTransBatchInsert0011 failed");
}
console.log(TAG + "************* testRdbTransBatchInsert0011 end *************");
done();
})
it('testRdbTransBatchInsert0012', 0, async (done) => {
console.log(TAG + "************* testRdbTransBatchInsert0012 start *************");
try {
const u8 = new Uint8Array([1, 2, 3]);
const rdbTrans = await rdbStore.createTransaction({
transactionType: data_relationalStore.TransactionType.EXCLUSIVE
});
const valueBuckets = new Array(100).fill(0).map(() => {
const valueBucket = {
"name": "lisi",
"age": 18,
"salary": 100.5,
"blobType": u8,
};
return valueBucket;
})
const rowCount = await rdbTrans.batchInsert("test", valueBuckets);
expect(rowCount).assertEqual(100);
await rdbTrans.rollback();
let predicates = new data_relationalStore.RdbPredicates("test");
let resultSet = await rdbStore.query(predicates);
console.log(TAG + "testRdbTransBatchInsert0012 result count " + resultSet.rowCount);
expect(0).assertEqual(resultSet.rowCount);
resultSet.close();
} catch (e) {
console.log(TAG + e);
expect(null).assertFail();
console.log(TAG + "testRdbTransBatchInsert0012 failed");
}
console.log(TAG + "************* testRdbTransBatchInsert0012 end *************");
done();
})
it('testRdbTransBatchInsert0013', 0, async (done) => {
console.log(TAG + "************* testRdbTransBatchInsert0013 start *************");
try {
const u8 = new Uint8Array([1, 2, 3]);
const rdbTrans = await rdbStore.createTransaction({
transactionType: data_relationalStore.TransactionType.IMMEDIATE
});
const valueBuckets = new Array(100).fill(0).map(() => {
const valueBucket = {
"name": "lisi",
"age": 18,
"salary": 100.5,
"blobType": u8,
};
return valueBucket;
})
const rowCount = await rdbTrans.batchInsert("test", valueBuckets);
expect(rowCount).assertEqual(100);
await rdbTrans.rollback();
let predicates = new data_relationalStore.RdbPredicates("test");
let resultSet = await rdbStore.query(predicates);
console.log(TAG + "testRdbTransBatchInsert0013 result count " + resultSet.rowCount);
expect(0).assertEqual(resultSet.rowCount);
resultSet.close();
} catch (e) {
console.log(TAG + e);
expect(null).assertFail();
console.log(TAG + "testRdbTransBatchInsert0013 failed");
}
console.log(TAG + "************* testRdbTransBatchInsert0013 end *************");
done();
})
it('testRdbTransBatchInsertSync0001', 0, async (done) => {
console.log(TAG + "************* testRdbTransBatchInsertSync0001 start *************");
try {
const u8 = new Uint8Array([1, 2, 3]);
const rdbTrans = await rdbStore.createTransaction({
transactionType: data_relationalStore.TransactionType.DEFERRED
});
const valueBuckets = new Array(100).fill(0).map(() => {
const valueBucket = {
"name": "lisi",
"age": 18,
"salary": 100.5,
"blobType": u8,
};
return valueBucket;
})
const rowCount = rdbTrans.batchInsertSync("test", valueBuckets);
expect(rowCount).assertEqual(100);
await rdbTrans.commit();
let predicates = new data_relationalStore.RdbPredicates("test");
let resultSet = await rdbStore.query(predicates);
console.log(TAG + "testRdbTransBatchInsertSync0001 result count " + resultSet.rowCount);
expect(100).assertEqual(resultSet.rowCount);
resultSet.close();
} catch (e) {
console.log(TAG + e);
expect(null).assertFail();
console.log(TAG + "testRdbTransBatchInsertSync0001 failed");
}
console.log(TAG + "************* testRdbTransBatchInsertSync0001 end *************");
done();
})
it('testRdbTransBatchInsertSync0002', 0, async (done) => {
console.log(TAG + "************* testRdbTransBatchInsertSync0002 start *************");
try {
const u8 = new Uint8Array([1, 2, 3]);
const rdbTrans = await rdbStore.createTransaction({
transactionType: data_relationalStore.TransactionType.EXCLUSIVE
});
const valueBuckets = new Array(100).fill(0).map(() => {
const valueBucket = {
"name": "lisi",
"age": 18,
"salary": 100.5,
"blobType": u8,
};
return valueBucket;
})
const rowCount = rdbTrans.batchInsertSync("test", valueBuckets);
expect(rowCount).assertEqual(100);
await rdbTrans.commit();
let predicates = new data_relationalStore.RdbPredicates("test");
let resultSet = await rdbStore.query(predicates);
console.log(TAG + "testRdbTransBatchInsertSync0002 result count " + resultSet.rowCount);
expect(100).assertEqual(resultSet.rowCount);
resultSet.close();
} catch (e) {
console.log(TAG + e);
expect(null).assertFail();
console.log(TAG + "testRdbTransBatchInsertSync0002 failed");
}
console.log(TAG + "************* testRdbTransBatchInsertSync0002 end *************");
done();
})
it('testRdbTransBatchInsertSync0003', 0, async (done) => {
console.log(TAG + "************* testRdbTransBatchInsertSync0003 start *************");
try {
const u8 = new Uint8Array([1, 2, 3]);
const rdbTrans = await rdbStore.createTransaction({
transactionType: data_relationalStore.TransactionType.IMMEDIATE
});
const valueBuckets = new Array(100).fill(0).map(() => {
const valueBucket = {
"name": "lisi",
"age": 18,
"salary": 100.5,
"blobType": u8,
};
return valueBucket;
})
const rowCount = rdbTrans.batchInsertSync("test", valueBuckets);
expect(rowCount).assertEqual(100);
await rdbTrans.commit();
let predicates = new data_relationalStore.RdbPredicates("test");
let resultSet = await rdbStore.query(predicates);
console.log(TAG + "testRdbTransBatchInsertSync0003 result count " + resultSet.rowCount);
expect(100).assertEqual(resultSet.rowCount);
resultSet.close();
} catch (e) {
console.log(TAG + e);
expect(null).assertFail();
console.log(TAG + "testRdbTransBatchInsertSync0003 failed");
}
console.log(TAG + "************* testRdbTransBatchInsertSync0003 end *************");
done();
})
it('testRdbTransBatchInsertSync0011', 0, async (done) => {
console.log(TAG + "************* testRdbTransBatchInsertSync0011 start *************");
try {
const u8 = new Uint8Array([1, 2, 3]);
const rdbTrans = await rdbStore.createTransaction({
transactionType: data_relationalStore.TransactionType.DEFERRED
});
const valueBuckets = new Array(100).fill(0).map(() => {
const valueBucket = {
"name": "lisi",
"age": 18,
"salary": 100.5,
"blobType": u8,
};
return valueBucket;
})
const rowCount = rdbTrans.batchInsertSync("test", valueBuckets);
expect(rowCount).assertEqual(100);
await rdbTrans.rollback();
let predicates = new data_relationalStore.RdbPredicates("test");
let resultSet = await rdbStore.query(predicates);
console.log(TAG + "testRdbTransBatchInsertSync0011 result count " + resultSet.rowCount);
expect(0).assertEqual(resultSet.rowCount);
resultSet.close();
} catch (e) {
console.log(TAG + e);
expect(null).assertFail();
console.log(TAG + "testRdbTransBatchInsertSync0011 failed");
}
console.log(TAG + "************* testRdbTransBatchInsertSync0011 end *************");
done();
})
it('testRdbTransBatchInsertSync0012', 0, async (done) => {
console.log(TAG + "************* testRdbTransBatchInsertSync0012 start *************");
try {
const u8 = new Uint8Array([1, 2, 3]);
const rdbTrans = await rdbStore.createTransaction({
transactionType: data_relationalStore.TransactionType.EXCLUSIVE
});
const valueBuckets = new Array(100).fill(0).map(() => {
const valueBucket = {
"name": "lisi",
"age": 18,
"salary": 100.5,
"blobType": u8,
};
return valueBucket;
})
const rowCount = rdbTrans.batchInsertSync("test", valueBuckets);
expect(rowCount).assertEqual(100);
await rdbTrans.rollback();
let predicates = new data_relationalStore.RdbPredicates("test");
let resultSet = await rdbStore.query(predicates);
console.log(TAG + "testRdbTransBatchInsertSync0012 result count " + resultSet.rowCount);
expect(0).assertEqual(resultSet.rowCount);
resultSet.close();
} catch (e) {
console.log(TAG + e);
expect(null).assertFail();
console.log(TAG + "testRdbTransBatchInsertSync0012 failed");
}
console.log(TAG + "************* testRdbTransBatchInsertSync0012 end *************");
done();
})
it('testRdbTransBatchInsertSync0013', 0, async (done) => {
console.log(TAG + "************* testRdbTransBatchInsertSync0013 start *************");
try {
const u8 = new Uint8Array([1, 2, 3]);
const rdbTrans = await rdbStore.createTransaction({
transactionType: data_relationalStore.TransactionType.IMMEDIATE
});
const valueBuckets = new Array(100).fill(0).map(() => {
const valueBucket = {
"name": "lisi",
"age": 18,
"salary": 100.5,
"blobType": u8,
};
return valueBucket;
})
const rowCount = rdbTrans.batchInsertSync("test", valueBuckets);
expect(rowCount).assertEqual(100);
await rdbTrans.rollback();
let predicates = new data_relationalStore.RdbPredicates("test");
let resultSet = await rdbStore.query(predicates);
console.log(TAG + "testRdbTransBatchInsertSync0013 result count " + resultSet.rowCount);
expect(0).assertEqual(resultSet.rowCount);
resultSet.close();
} catch (e) {
console.log(TAG + e);
expect(null).assertFail();
console.log(TAG + "testRdbTransBatchInsertSync0013 failed");
}
console.log(TAG + "************* testRdbTransBatchInsertSync0013 end *************");
done();
})
it('testRdbTransUpdate0001', 0, async (done) => {
console.log(TAG + "************* testRdbTransUpdate0001 start *************");
try {
const u8 = new Uint8Array([1, 2, 3]);
const rdbTrans = await rdbStore.createTransaction({
transactionType: data_relationalStore.TransactionType.DEFERRED
});
const valueBucket = {
"name": "lisi",
"age": 18,
"salary": 100.5,
"blobType": u8,
};
const rowId = await rdbTrans.insert("test", valueBucket);
expect(rowId).assertEqual(1);
const updatePredicates = new data_relationalStore.RdbPredicates("test");
updatePredicates.equalTo('name', 'lisi');
await rdbTrans.update({ age: 20 }, updatePredicates);
await rdbTrans.commit();
let predicates = new data_relationalStore.RdbPredicates("test");
let resultSet = await rdbStore.query(predicates);
console.log(TAG + "testRdbTransUpdate0001 result count " + resultSet.rowCount);
expect(1).assertEqual(resultSet.rowCount);
resultSet.goToFirstRow();
const rowData = resultSet.getRow();
expect(rowData['age']).assertEqual(20);
resultSet.close();
} catch (e) {
console.log(TAG + e);
expect(null).assertFail();
console.log(TAG + "testRdbTransUpdate0001 failed");
}
console.log(TAG + "************* testRdbTransUpdate0001 end *************");
done();
})
it('testRdbTransUpdate0002', 0, async (done) => {
console.log(TAG + "************* testRdbTransUpdate0002 start *************");
try {
const u8 = new Uint8Array([1, 2, 3]);
const rdbTrans = await rdbStore.createTransaction({
transactionType: data_relationalStore.TransactionType.EXCLUSIVE
});
const valueBucket = {
"name": "lisi",
"age": 18,
"salary": 100.5,
"blobType": u8,
};
const rowId = await rdbTrans.insert("test", valueBucket);
expect(rowId).assertEqual(1);
const updatePredicates = new data_relationalStore.RdbPredicates("test");
updatePredicates.equalTo('name', 'lisi');
await rdbTrans.update({ age: 20 }, updatePredicates);
await rdbTrans.commit();
let predicates = new data_relationalStore.RdbPredicates("test");
let resultSet = await rdbStore.query(predicates);
console.log(TAG + "testRdbTransUpdate0002 result count " + resultSet.rowCount);
expect(1).assertEqual(resultSet.rowCount);
resultSet.goToFirstRow();
const rowData = resultSet.getRow();
expect(rowData['age']).assertEqual(20);
resultSet.close();
} catch (e) {
console.log(TAG + e);
expect(null).assertFail();
console.log(TAG + "testRdbTransUpdate0002 failed");
}
console.log(TAG + "************* testRdbTransUpdate0002 end *************");
done();
})
it('testRdbTransUpdate0003', 0, async (done) => {
console.log(TAG + "************* testRdbTransUpdate0003 start *************");
try {
const u8 = new Uint8Array([1, 2, 3]);
const rdbTrans = await rdbStore.createTransaction({
transactionType: data_relationalStore.TransactionType.IMMEDIATE
});
const valueBucket = {
"name": "lisi",
"age": 18,
"salary": 100.5,
"blobType": u8,
};
const rowId = await rdbTrans.insert("test", valueBucket);
expect(rowId).assertEqual(1);
const updatePredicates = new data_relationalStore.RdbPredicates("test");
updatePredicates.equalTo('name', 'lisi');
await rdbTrans.update({ age: 20 }, updatePredicates);
await rdbTrans.commit();
let predicates = new data_relationalStore.RdbPredicates("test");
let resultSet = await rdbStore.query(predicates);
console.log(TAG + "testRdbTransUpdate0003 result count " + resultSet.rowCount);
expect(1).assertEqual(resultSet.rowCount);
resultSet.goToFirstRow();
const rowData = resultSet.getRow();
expect(rowData['age']).assertEqual(20);
resultSet.close();
} catch (e) {
console.log(TAG + e);
expect(null).assertFail();
console.log(TAG + "testRdbTransUpdate0003 failed");
}
console.log(TAG + "************* testRdbTransUpdate0003 end *************");
done();
})
console.log(TAG + "*************Unit Test End*************");
})

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -105,6 +105,7 @@ ohos_unittest("NativeRdbTest") {
"unittest/rdb_store_interface_test.cpp",
"unittest/rdb_store_rekey_test.cpp",
"unittest/rdb_store_subscribe_test.cpp",
"unittest/rdb_trans_db_test.cpp",
"unittest/rdb_transaction_test.cpp",
"unittest/rdb_update_test.cpp",
"unittest/rdb_upgrade_test.cpp",
@ -112,6 +113,8 @@ ohos_unittest("NativeRdbTest") {
"unittest/rdb_value_bucket_test.cpp",
"unittest/rdb_wal_limit_test.cpp",
"unittest/sqlite_utils_test.cpp",
"unittest/transaction_test.cpp",
"unittest/value_object_test.cpp",
]
sources += [
@ -129,10 +132,10 @@ ohos_unittest("NativeRdbTest") {
"../../../frameworks/native/rdb/src/connection_pool.cpp",
"../../../frameworks/native/rdb/src/grd_api_manager.cpp",
"../../../frameworks/native/rdb/src/raw_data_parser.cpp",
"../../../frameworks/native/rdb/src/rdb_local_db_observer.cpp",
"../../../frameworks/native/rdb/src/rd_connection.cpp",
"../../../frameworks/native/rdb/src/rd_statement.cpp",
"../../../frameworks/native/rdb/src/rd_utils.cpp",
"../../../frameworks/native/rdb/src/rdb_local_db_observer.cpp",
"../../../frameworks/native/rdb/src/rdb_security_manager.cpp",
"../../../frameworks/native/rdb/src/rdb_sql_statistic.cpp",
"../../../frameworks/native/rdb/src/sqlite_connection.cpp",
@ -141,8 +144,10 @@ ohos_unittest("NativeRdbTest") {
"../../../frameworks/native/rdb/src/sqlite_sql_builder.cpp",
"../../../frameworks/native/rdb/src/sqlite_statement.cpp",
"../../../frameworks/native/rdb/src/sqlite_utils.cpp",
"../../../frameworks/native/rdb/src/step_result_set.cpp",
"../../../frameworks/native/rdb/src/string_utils.cpp",
"../../../frameworks/native/rdb/src/task_executor.cpp",
"../../../frameworks/native/rdb/src/trans_db.cpp",
]
configs = [ ":module_private_config" ]

View File

@ -16,7 +16,6 @@
#include "raw_data_parser.h"
#include <gtest/gtest.h>
#include "value_object.h"
using namespace testing::ext;
using namespace OHOS::NativeRdb;

View File

@ -24,7 +24,7 @@
using namespace testing::ext;
using namespace OHOS::NativeRdb;
namespace Test {
class RdbReadOnlyTest : public testing::Test {
public:
static void SetUpTestCase(void);
@ -504,3 +504,25 @@ HWTEST_F(RdbReadOnlyTest, RdbStore_ReadOnly_0022, TestSize.Level1)
auto ret = store->CleanDirtyData("test", cursor);
EXPECT_EQ(E_NOT_SUPPORT, ret);
}
/**
* @tc.name: RdbStore_CreateTransaction_001
* @tc.desc: test Create Transaction
* @tc.type: FUNC
*/
HWTEST_F(RdbReadOnlyTest, RdbStore_CreateTransaction_001, TestSize.Level1)
{
std::shared_ptr<RdbStore> &store = RdbReadOnlyTest::readOnlyStore;
auto [errCode, trans] = store->CreateTransaction(Transaction::DEFERRED);
EXPECT_EQ(E_NOT_SUPPORT, errCode);
EXPECT_EQ(trans, nullptr);
std::tie(errCode, trans) = store->CreateTransaction(Transaction::IMMEDIATE);
EXPECT_EQ(E_NOT_SUPPORT, errCode);
EXPECT_EQ(trans, nullptr);
std::tie(errCode, trans) = store->CreateTransaction(Transaction::EXCLUSIVE);
EXPECT_EQ(E_NOT_SUPPORT, errCode);
EXPECT_EQ(trans, nullptr);
}
}

View File

@ -21,6 +21,7 @@
#include "common.h"
#include "rdb_errno.h"
#include "rdb_helper.h"
#include "file_ex.h"
using namespace testing::ext;
@ -57,6 +58,18 @@ void RdbSecurityManagerTest::TearDown(void)
{
}
class RdbStoreSecurityManagerTestOpenCallback : public RdbOpenCallback {
public:
int OnCreate(RdbStore &store) override
{
return E_OK;
}
int OnUpgrade(RdbStore &store, int oldVersion, int newVersion) override
{
return E_OK;
}
};
/**
* @tc.name: Insert_BigInt_INT64
* @tc.desc: test insert bigint to rdb store
@ -108,16 +121,30 @@ HWTEST_F(RdbSecurityManagerTest, LockUnlock, TestSize.Level1)
*/
HWTEST_F(RdbSecurityManagerTest, LoadSecretKeyFromDiskTest, TestSize.Level1)
{
int errCode = E_OK;
std::string name = "secret_key_load_test";
auto keyPath = RDB_TEST_PATH + "key/" + name + ".pub_key";
RdbSecurityManager::KeyFiles keyFile(keyPath);
RdbStoreConfig config(RDB_TEST_PATH + name);
config.SetEncryptStatus(true);
RdbStoreSecurityManagerTestOpenCallback helper;
auto store = RdbHelper::GetRdbStore(config, 1, helper, errCode);
EXPECT_EQ(errCode, E_OK);
EXPECT_NE(store, nullptr);
RdbSecurityManager::KeyFiles keyFile(RDB_TEST_PATH);
const std::string file = keyFile.GetKeyFile(RdbSecurityManager::KeyFileType::PUB_KEY_FILE);
std::vector<char> content = { 'a' };
bool ret = OHOS::SaveBufferToFile(file, content);
ASSERT_TRUE(ret);
RdbPassword pwd =
RdbSecurityManager::GetInstance().GetRdbPassword(keyPath, RdbSecurityManager::KeyFileType::PUB_KEY_FILE);
RdbSecurityManager::GetInstance().GetRdbPassword(RDB_TEST_PATH, RdbSecurityManager::KeyFileType::PUB_KEY_FILE);
ASSERT_EQ(pwd.GetSize(), 0);
auto store1 = RdbHelper::GetRdbStore(config, 1, helper, errCode);
EXPECT_EQ(errCode, E_OK);
EXPECT_NE(store1, nullptr);
RdbHelper::DeleteRdbStore(config);
}
}

View File

@ -784,4 +784,151 @@ HWTEST_F(RdbStoreImplTest, UnlockCloudContainerTest, TestSize.Level2)
EXPECT_NE(E_OK, result);
store = nullptr;
RdbHelper::DeleteRdbStore(RdbStoreImplTest::DATABASE_NAME);
}
}
/* *
* @tc.name: LockCloudContainerTest001
* @tc.desc: lock cloudContainer testCase
* @tc.type: FUNC
*/
HWTEST_F(RdbStoreImplTest, LockCloudContainerTest001, TestSize.Level2)
{
int errCode = E_OK;
RdbStoreConfig config(RdbStoreImplTest::DATABASE_NAME);
config.SetName("RdbStore_impl_test.db");
config.SetBundleName("com.example.distributed.rdb");
RdbStoreImplTestOpenCallback helper;
std::shared_ptr<RdbStore> store = RdbHelper::GetRdbStore(config, 1, helper, errCode);
ASSERT_NE(store, nullptr);
EXPECT_EQ(E_OK, errCode);
// GetRdbService succeeded if configuration file has already been configured
auto ret = store->RdbStore::LockCloudContainer();
EXPECT_EQ(E_OK, ret.first);
EXPECT_EQ(0, ret.second);
store = nullptr;
RdbHelper::DeleteRdbStore(RdbStoreImplTest::DATABASE_NAME);
}
/* *
* @tc.name: UnlockCloudContainerTest001
* @tc.desc: unlock cloudContainer testCase
* @tc.type: FUNC
*/
HWTEST_F(RdbStoreImplTest, UnlockCloudContainerTest001, TestSize.Level2)
{
int errCode = E_OK;
RdbStoreConfig config(RdbStoreImplTest::DATABASE_NAME);
config.SetName("RdbStore_impl_test.db");
config.SetBundleName("com.example.distributed.rdb");
RdbStoreImplTestOpenCallback helper;
std::shared_ptr<RdbStore> store = RdbHelper::GetRdbStore(config, 1, helper, errCode);
ASSERT_NE(store, nullptr);
EXPECT_EQ(E_OK, errCode);
// GetRdbService succeeded if configuration file has already been configured
auto result = store->RdbStore::UnlockCloudContainer();
EXPECT_EQ(E_OK, result);
store = nullptr;
RdbHelper::DeleteRdbStore(RdbStoreImplTest::DATABASE_NAME);
}
/* *
* @tc.name: SetSearchableTest
* @tc.desc: SetSearchable testCase
* @tc.type: FUNC
*/
HWTEST_F(RdbStoreImplTest, SetSearchableTest, TestSize.Level2)
{
int errCode = E_OK;
RdbStoreConfig config(RdbStoreImplTest::DATABASE_NAME);
config.SetBundleName("");
RdbStoreImplTestOpenCallback helper;
std::shared_ptr<RdbStore> store = RdbHelper::GetRdbStore(config, 1, helper, errCode);
EXPECT_EQ(E_OK, errCode);
int result = store->SetSearchable(true);
EXPECT_EQ(E_INVALID_ARGS, result);
RdbHelper::DeleteRdbStore(RdbStoreImplTest::DATABASE_NAME);
config.SetBundleName("com.example.distributed.rdb");
EXPECT_EQ(E_OK, errCode);
store = RdbHelper::GetRdbStore(config, 1, helper, errCode);
EXPECT_EQ(E_OK, errCode);
result = store->SetSearchable(true);
EXPECT_EQ(E_OK, result);
}
/* *
* @tc.name: CreateTransaction_001
* @tc.desc: create the DEFERRED, IMMEDIATE, EXCLUSIVE transaction.
* @tc.type: FUNC
*/
HWTEST_F(RdbStoreImplTest, CreateTransaction_001, TestSize.Level1)
{
auto [errCode, trans] = store_->CreateTransaction(Transaction::DEFERRED);
ASSERT_EQ(errCode, E_OK);
ASSERT_NE(trans, nullptr);
trans = nullptr;
std::tie(errCode, trans) = store_->CreateTransaction(Transaction::IMMEDIATE);
ASSERT_EQ(errCode, E_OK);
ASSERT_NE(trans, nullptr);
trans = nullptr;
std::tie(errCode, trans) = store_->CreateTransaction(Transaction::EXCLUSIVE);
ASSERT_EQ(errCode, E_OK);
ASSERT_NE(trans, nullptr);
}
/* *
* @tc.name: CreateTransaction_002
* @tc.desc: create the invalid type transaction.
* @tc.type: FUNC
*/
HWTEST_F(RdbStoreImplTest, CreateTransaction_002, TestSize.Level1)
{
auto [errCode, trans] = store_->CreateTransaction(-1);
ASSERT_EQ(errCode, E_INVALID_ARGS);
ASSERT_EQ(trans, nullptr);
std::tie(errCode, trans) = store_->CreateTransaction(Transaction::TRANS_BUTT);
ASSERT_EQ(errCode, E_INVALID_ARGS);
ASSERT_EQ(trans, nullptr);
std::tie(errCode, trans) = store_->CreateTransaction(100);
ASSERT_EQ(errCode, E_INVALID_ARGS);
ASSERT_EQ(trans, nullptr);
}
/* *
* @tc.name: CreateTransaction_003
* @tc.desc: create the over the max trans.
* @tc.type: FUNC
*/
HWTEST_F(RdbStoreImplTest, CreateTransaction_003, TestSize.Level1)
{
constexpr size_t MAX_TRANS = 4;
std::vector<std::shared_ptr<Transaction>> entries;
int32_t errCode = E_OK;
std::shared_ptr<Transaction> trans = nullptr;
for (int i = 0; i < 100; ++i) {
std::tie(errCode, trans) = store_->CreateTransaction(Transaction::DEFERRED);
if (trans == nullptr) {
break;
}
entries.push_back(std::move(trans));
}
ASSERT_EQ(errCode, E_DATABASE_BUSY);
ASSERT_EQ(entries.size(), MAX_TRANS);
}
/* *
* @tc.name: CreateTransaction_004
* @tc.desc: create the auto release trans.
* @tc.type: FUNC
*/
HWTEST_F(RdbStoreImplTest, CreateTransaction_004, TestSize.Level1)
{
int i = 0;
for (i = 0; i < 20; ++i) {
auto [errCode, trans] = store_->CreateTransaction(Transaction::EXCLUSIVE);
ASSERT_EQ(errCode, E_OK);
ASSERT_NE(trans, nullptr);
}
ASSERT_EQ(i, 20);
}

File diff suppressed because it is too large Load Diff

View File

@ -578,6 +578,39 @@ HWTEST_F(RdbStoreUpdateTest, RdbStore_UpdateWithConflictResolution_006, TestSize
EXPECT_EQ(ret, E_OK);
}
/**
* @tc.name: RdbStore_UpdateWithConflictResolution_007
* @tc.desc: test RdbStore UpdateWithConflictResolution
* @tc.type: FUNC
*/
HWTEST_F(RdbStoreUpdateTest, RdbStore_UpdateWithConflictResolution_007, TestSize.Level1)
{
std::shared_ptr<RdbStore> &store = RdbStoreUpdateTest::store;
int changedRows = 0;
int64_t id = -1;
ValuesBucket values;
int ret = store->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[0]));
EXPECT_EQ(ret, E_OK);
EXPECT_EQ(1, id);
values.PutInt("id", 2);
values.PutInt("age", 19);
ret = store->UpdateWithConflictResolution(changedRows, "test", values, "age = ?", std::vector<std::string>{ "18" },
static_cast<ConflictResolution>(6));
EXPECT_EQ(E_INVALID_CONFLICT_FLAG, ret);
EXPECT_EQ(0, changedRows);
values.Clear();
values.PutInt("id", 2);
values.PutInt("age", 19);
ret = store->UpdateWithConflictResolution(changedRows, "test", values, "age = ?", std::vector<std::string>{ "18" },
static_cast<ConflictResolution>(-1));
EXPECT_EQ(E_INVALID_CONFLICT_FLAG, ret);
EXPECT_EQ(0, changedRows);
}
/**
* @tc.name: RdbStore_UpdateSqlBuilder_001
* @tc.desc: test RdbStore UpdateSqlBuilder

View File

@ -247,36 +247,35 @@ HWTEST_F(RdbWalLimitTest, RdbStore_WalOverLimit_002, TestSize.Level1)
}
/**
@tc.name: RdbStore_WalOverLimit_003
@tc.desc: During transactions, the size of the wal file may exceed the limit.
@tc.type: FUNC
@tc.acquire: AR000HR0G5
*/
* @tc.name: RdbStore_WalOverLimit_003
* @tc.desc: During transactions, the size of the wal file may exceed the limit.
* @tc.type: FUNC
* @tc.acquire: AR000HR0G5
*/
HWTEST_F(RdbWalLimitTest, RdbStore_WalOverLimit_003, TestSize.Level3)
{
ValuesBucket values = MakeValueBucket(200);
int64_t id;
store->BeginTransaction();
MakeWalReachLimit();
EXPECT_EQ(store->Insert(id, "test", values), E_WAL_SIZE_OVER_LIMIT);
int errCode = store->Commit();
EXPECT_EQ(errCode, E_OK);
ValuesBucket values = MakeValueBucket(200);
int64_t id;
store->BeginTransaction();
MakeWalReachLimit();
EXPECT_EQ(store->Insert(id, "test", values), E_WAL_SIZE_OVER_LIMIT);
int errCode = store->Commit();
EXPECT_EQ(errCode, E_OK);
}
/**
@tc.name: RdbStore_WalOverLimit_003
@tc.desc: During transactions, the size of the wal file may exceed the limit.
@tc.type: FUNC
@tc.acquire: AR000HR0G5
*/
/**
* @tc.name: RdbStore_WalOverLimit_003
* @tc.desc: During transactions, the size of the wal file may exceed the limit.
* @tc.type: FUNC
* @tc.acquire: AR000HR0G5
*/
HWTEST_F(RdbWalLimitTest, RdbStore_WalOverLimit_004, TestSize.Level3)
{
ValuesBucket values = MakeValueBucket(200);
int64_t id;
store->BeginTransaction();
MakeWalReachLimit();
EXPECT_EQ(store->Insert(id, "test", values), E_WAL_SIZE_OVER_LIMIT);
int errCode = store->RollBack();
EXPECT_EQ(errCode, E_OK);
ValuesBucket values = MakeValueBucket(200);
int64_t id;
store->BeginTransaction();
MakeWalReachLimit();
EXPECT_EQ(store->Insert(id, "test", values), E_WAL_SIZE_OVER_LIMIT);
int errCode = store->RollBack();
EXPECT_EQ(errCode, E_OK);
}

View File

@ -0,0 +1,391 @@
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <gtest/gtest.h>
#include <string>
#include "common.h"
#include "rdb_errno.h"
#include "rdb_helper.h"
#include "rdb_open_callback.h"
using namespace testing::ext;
using namespace OHOS::NativeRdb;
static const std::string DATABASE_NAME = RDB_TEST_PATH + "transaction_test.db";
static const char CREATE_TABLE_SQL[] =
"CREATE TABLE IF NOT EXISTS test "
"(id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, age INTEGER, salary REAL, blobType BLOB)";
class TransactionTest : public testing::Test {
public:
static void SetUpTestCase();
static void TearDownTestCase();
void SetUp() override;
void TearDown() override;
static inline std::shared_ptr<RdbStore> store_;
class TransactionTestOpenCallback : public RdbOpenCallback {
public:
int OnCreate(RdbStore &store) override;
int OnUpgrade(RdbStore &store, int oldVersion, int newVersion) override;
};
};
int TransactionTest::TransactionTestOpenCallback::OnCreate(RdbStore &store)
{
auto [ret, value] = store.Execute(CREATE_TABLE_SQL);
return ret;
}
int TransactionTest::TransactionTestOpenCallback::OnUpgrade(RdbStore &store, int oldVersion, int newVersion)
{
return E_OK;
}
void TransactionTest::SetUpTestCase()
{
int errCode = E_OK;
RdbHelper::DeleteRdbStore(DATABASE_NAME);
RdbStoreConfig config(DATABASE_NAME);
TransactionTestOpenCallback helper;
TransactionTest::store_ = RdbHelper::GetRdbStore(config, 1, helper, errCode);
EXPECT_NE(TransactionTest::store_, nullptr);
EXPECT_EQ(errCode, E_OK);
}
void TransactionTest::TearDownTestCase()
{
store_ = nullptr;
RdbHelper::DeleteRdbStore(DATABASE_NAME);
}
void TransactionTest::SetUp()
{
store_->Execute("DELETE FROM test");
}
void TransactionTest::TearDown()
{
}
/**
* @tc.name: RdbStore_Transaction_001
* @tc.desc: createTransaction and commit
* @tc.type: FUNC
*/
HWTEST_F(TransactionTest, RdbStore_Transaction_001, TestSize.Level1)
{
std::shared_ptr<RdbStore> &store = TransactionTest::store_;
auto [ret, transaction] = store->CreateTransaction(Transaction::EXCLUSIVE);
ASSERT_EQ(ret, E_OK);
ASSERT_NE(transaction, nullptr);
auto result = transaction->Insert("test", UTUtils::SetRowData(UTUtils::g_rowData[0]));
ASSERT_EQ(result.first, E_OK);
ASSERT_EQ(1, result.second);
result = transaction->Insert("test", UTUtils::SetRowData(UTUtils::g_rowData[1]));
ASSERT_EQ(result.first, E_OK);
ASSERT_EQ(2, result.second);
result = store->Insert("test", UTUtils::SetRowData(UTUtils::g_rowData[2]), RdbStore::NO_ACTION);
ASSERT_EQ(result.first, E_SQLITE_BUSY);
auto resultSet = transaction->QueryByStep("SELECT * FROM test");
ASSERT_NE(resultSet, nullptr);
int32_t rowCount{};
ret = resultSet->GetRowCount(rowCount);
ASSERT_EQ(ret, E_OK);
ASSERT_EQ(rowCount, 2);
ret = transaction->Commit();
ASSERT_EQ(ret, E_OK);
ValueObject value;
ret = resultSet->Get(0, value);
ASSERT_EQ(ret, E_ALREADY_CLOSED);
result = store->Insert("test", UTUtils::SetRowData(UTUtils::g_rowData[2]), RdbStore::NO_ACTION);
ASSERT_EQ(result.first, E_OK);
ASSERT_EQ(3, result.second);
result = transaction->Insert("test", UTUtils::SetRowData(UTUtils::g_rowData[0]));
ASSERT_EQ(result.first, E_ALREADY_CLOSED);
resultSet = store->QueryByStep("SELECT * FROM test");
ASSERT_NE(resultSet, nullptr);
resultSet->GetRowCount(rowCount);
EXPECT_EQ(rowCount, 3);
}
/**
* @tc.name: RdbStore_Transaction_002
* @tc.desc: createTransaction and rollback
* @tc.type: FUNC
*/
HWTEST_F(TransactionTest, RdbStore_Transaction_002, TestSize.Level1)
{
std::shared_ptr<RdbStore> &store = TransactionTest::store_;
auto [ret, transaction] = store->CreateTransaction(Transaction::EXCLUSIVE);
ASSERT_EQ(ret, E_OK);
ASSERT_NE(transaction, nullptr);
auto result = transaction->Insert("test", UTUtils::SetRowData(UTUtils::g_rowData[0]));
ASSERT_EQ(result.first, E_OK);
ASSERT_EQ(1, result.second);
result = transaction->Insert("test", UTUtils::SetRowData(UTUtils::g_rowData[1]));
ASSERT_EQ(result.first, E_OK);
ASSERT_EQ(2, result.second);
ret = transaction->Rollback();
ASSERT_EQ(ret, E_OK);
auto resultSet = store->QueryByStep("SELECT * FROM test");
ASSERT_NE(resultSet, nullptr);
int32_t rowCount{};
ret = resultSet->GetRowCount(rowCount);
ASSERT_EQ(ret, E_OK);
ASSERT_EQ(rowCount, 0);
result = store->Insert("test", UTUtils::SetRowData(UTUtils::g_rowData[2]), RdbStore::NO_ACTION);
ASSERT_EQ(result.first, E_OK);
ASSERT_EQ(3, result.second);
result = transaction->Insert("test", UTUtils::SetRowData(UTUtils::g_rowData[0]));
ASSERT_EQ(result.first, E_ALREADY_CLOSED);
resultSet = store->QueryByStep("SELECT * FROM test");
ASSERT_NE(resultSet, nullptr);
ret = resultSet->GetRowCount(rowCount);
EXPECT_EQ(ret, E_OK);
EXPECT_EQ(rowCount, 1);
}
/**
* @tc.name: RdbStore_Transaction_003
* @tc.desc: batchInsert
* @tc.type: FUNC
*/
HWTEST_F(TransactionTest, RdbStore_Transaction_003, TestSize.Level1)
{
std::shared_ptr<RdbStore> &store = TransactionTest::store_;
auto [ret, transaction] = store->CreateTransaction(Transaction::EXCLUSIVE);
ASSERT_EQ(ret, E_OK);
ASSERT_NE(transaction, nullptr);
Transaction::Rows rows {
UTUtils::SetRowData(UTUtils::g_rowData[0]),
UTUtils::SetRowData(UTUtils::g_rowData[1]),
UTUtils::SetRowData(UTUtils::g_rowData[2]),
};
auto result = transaction->BatchInsert("test", rows);
ASSERT_EQ(result.first, E_OK);
ASSERT_EQ(result.second, 3);
ret = transaction->Commit();
ASSERT_EQ(ret, E_OK);
auto resultSet = store->QueryByStep("SELECT * FROM test");
ASSERT_NE(resultSet, nullptr);
int32_t rowCount{};
ret = resultSet->GetRowCount(rowCount);
EXPECT_EQ(ret, E_OK);
EXPECT_EQ(rowCount, 3);
}
/**
* @tc.name: RdbStore_Transaction_004
* @tc.desc: batchInsert
* @tc.type: FUNC
*/
HWTEST_F(TransactionTest, RdbStore_Transaction_004, TestSize.Level1)
{
std::shared_ptr<RdbStore> &store = TransactionTest::store_;
auto [ret, transaction] = store->CreateTransaction(Transaction::EXCLUSIVE);
ASSERT_EQ(ret, E_OK);
ASSERT_NE(transaction, nullptr);
Transaction::RefRows rows;
rows.Put(UTUtils::SetRowData(UTUtils::g_rowData[0]));
rows.Put(UTUtils::SetRowData(UTUtils::g_rowData[1]));
rows.Put(UTUtils::SetRowData(UTUtils::g_rowData[2]));
auto result = transaction->BatchInsert("test", rows);
ASSERT_EQ(result.first, E_OK);
ASSERT_EQ(result.second, 3);
ret = transaction->Commit();
ASSERT_EQ(ret, E_OK);
auto resultSet = store->QueryByStep("SELECT * FROM test");
ASSERT_NE(resultSet, nullptr);
int32_t rowCount{};
ret = resultSet->GetRowCount(rowCount);
EXPECT_EQ(ret, E_OK);
EXPECT_EQ(rowCount, 3);
}
/**
* @tc.name: RdbStore_Transaction_005
* @tc.desc: Update
* @tc.type: FUNC
*/
HWTEST_F(TransactionTest, RdbStore_Transaction_005, TestSize.Level1)
{
std::shared_ptr<RdbStore> &store = TransactionTest::store_;
auto [ret, transaction] = store->CreateTransaction(Transaction::EXCLUSIVE);
ASSERT_EQ(ret, E_OK);
ASSERT_NE(transaction, nullptr);
auto result = transaction->Insert("test", UTUtils::SetRowData(UTUtils::g_rowData[0]));
ASSERT_EQ(result.first, E_OK);
ASSERT_EQ(result.second, 1);
result = transaction->Update("test", UTUtils::SetRowData(UTUtils::g_rowData[1]), "id=1");
ASSERT_EQ(result.first, E_OK);
ASSERT_EQ(result.second, 1);
auto resultSet = transaction->QueryByStep("SELECT * FROM test");
ASSERT_NE(resultSet, nullptr);
int32_t rowCount{};
ret = resultSet->GetRowCount(rowCount);
ASSERT_EQ(ret, E_OK);
ASSERT_EQ(rowCount, 1);
ret = resultSet->GoToFirstRow();
ASSERT_EQ(ret, E_OK);
int32_t columnIndex{};
ret = resultSet->GetColumnIndex("id", columnIndex);
ASSERT_EQ(ret, E_OK);
int32_t id{};
ret = resultSet->GetInt(columnIndex, id);
ASSERT_EQ(ret, E_OK);
ASSERT_EQ(id, 2);
AbsRdbPredicates predicates("test");
predicates.EqualTo("id", ValueObject(2));
result = transaction->Update(UTUtils::SetRowData(UTUtils::g_rowData[2]), predicates);
ASSERT_EQ(result.first, E_OK);
ASSERT_EQ(result.second, 1);
ret = transaction->Commit();
ASSERT_EQ(ret, E_OK);
resultSet = store->QueryByStep("SELECT * FROM test");
ASSERT_NE(resultSet, nullptr);
ret = resultSet->GetRowCount(rowCount);
ASSERT_EQ(ret, E_OK);
ASSERT_EQ(rowCount, 1);
ret = resultSet->GoToFirstRow();
ASSERT_EQ(ret, E_OK);
resultSet->GetColumnIndex("id", columnIndex);
ret = resultSet->GetInt(columnIndex, id);
EXPECT_EQ(ret, E_OK);
EXPECT_EQ(id, 3);
}
/**
* @tc.name: RdbStore_Transaction_006
* @tc.desc: Delete
* @tc.type: FUNC
*/
HWTEST_F(TransactionTest, RdbStore_Transaction_006, TestSize.Level1)
{
std::shared_ptr<RdbStore> &store = TransactionTest::store_;
auto [ret, transaction] = store->CreateTransaction(Transaction::EXCLUSIVE);
ASSERT_EQ(ret, E_OK);
ASSERT_NE(transaction, nullptr);
Transaction::RefRows rows;
rows.Put(UTUtils::SetRowData(UTUtils::g_rowData[0]));
rows.Put(UTUtils::SetRowData(UTUtils::g_rowData[1]));
rows.Put(UTUtils::SetRowData(UTUtils::g_rowData[2]));
auto result = transaction->BatchInsert("test", rows);
ASSERT_EQ(result.first, E_OK);
ASSERT_EQ(result.second, 3);
result = transaction->Delete("test", "id=1");
ASSERT_EQ(result.first, E_OK);
ASSERT_EQ(result.second, 1);
AbsRdbPredicates predicates("test");
predicates.EqualTo("id", ValueObject(2));
result = transaction->Delete(predicates);
ASSERT_EQ(result.first, E_OK);
ASSERT_EQ(result.second, 1);
ret = transaction->Commit();
ASSERT_EQ(ret, E_OK);
auto resultSet = store->QueryByStep("SELECT * FROM test");
ASSERT_NE(resultSet, nullptr);
int32_t rowCount{};
ret = resultSet->GetRowCount(rowCount);
ASSERT_EQ(ret, E_OK);
ASSERT_EQ(rowCount, 1);
ret = resultSet->GoToFirstRow();
ASSERT_EQ(ret, E_OK);
int32_t columnIndex{};
resultSet->GetColumnIndex("id", columnIndex);
int32_t id{};
ret = resultSet->GetInt(columnIndex, id);
EXPECT_EQ(ret, E_OK);
EXPECT_EQ(id, 3);
}
/**
* @tc.name: RdbStore_Transaction_007
* @tc.desc: Execute
* @tc.type: FUNC
*/
HWTEST_F(TransactionTest, RdbStore_Transaction_007, TestSize.Level1)
{
std::shared_ptr<RdbStore> &store = TransactionTest::store_;
auto [ret, transaction] = store->CreateTransaction(Transaction::EXCLUSIVE);
ASSERT_EQ(ret, E_OK);
ASSERT_NE(transaction, nullptr);
auto res = transaction->Execute(
"CREATE TABLE IF NOT EXISTS test1 (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL)");
ASSERT_EQ(res.first, E_OK);
Transaction::Row row;
row.Put("id", 1);
row.Put("name", "Jim");
auto result = transaction->Insert("test1", row);
ASSERT_EQ(result.first, E_OK);
ASSERT_EQ(result.second, 1);
ret = transaction->Commit();
ASSERT_EQ(ret, E_OK);
auto resultSet = store->QueryByStep("SELECT * FROM test1");
ASSERT_NE(resultSet, nullptr);
int32_t rowCount{};
ret = resultSet->GetRowCount(rowCount);
EXPECT_EQ(ret, E_OK);
EXPECT_EQ(rowCount, 1);
}