mirror of
https://gitee.com/openharmony/distributeddatamgr_relational_store
synced 2024-11-23 07:00:41 +00:00
feature:add createTransacion
Signed-off-by: htt1997 <hutao105@huawei.com>
This commit is contained in:
parent
a48812841f
commit
ba4faabcc4
@ -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;
|
||||
};
|
||||
|
@ -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",
|
||||
]
|
||||
|
||||
|
@ -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
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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
|
@ -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_;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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]);
|
||||
|
@ -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 ¶m)
|
||||
{
|
||||
std::shared_ptr<Context> context = JSAbility::GetCurrentAbility(env, jsValue);
|
||||
|
@ -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
|
||||
|
670
frameworks/js/napi/relationalstore/src/napi_transaction.cpp
Normal file
670
frameworks/js/napi/relationalstore/src/napi_transaction.cpp
Normal 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
|
@ -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
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
|
@ -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 ¶m);
|
||||
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_;
|
||||
|
@ -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_;
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
48
frameworks/native/rdb/include/trans_db.h
Normal file
48
frameworks/native/rdb/include/trans_db.h
Normal 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
|
72
frameworks/native/rdb/include/transaction_impl.h
Normal file
72
frameworks/native/rdb/include/transaction_impl.h
Normal 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
|
@ -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 ¬ifier) = 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
|
@ -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
|
@ -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
|
||||
|
@ -49,8 +49,8 @@ private:
|
||||
bool IsConfigInvalidChanged(const std::string &path, RdbStoreConfig &config);
|
||||
int32_t GetParamFromService(DistributedRdb::RdbSyncerParam ¶m);
|
||||
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_;
|
||||
|
@ -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_;
|
||||
|
@ -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
|
@ -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)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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) {
|
||||
|
603
frameworks/native/rdb/src/rdb_store.cpp
Normal file
603
frameworks/native/rdb/src/rdb_store.cpp
Normal 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
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include <chrono>
|
||||
#include <cerrno>
|
||||
#include <cinttypes>
|
||||
#include <cstring>
|
||||
#include "logger.h"
|
||||
#include "sqlite3sym.h"
|
||||
#include "sqlite_utils.h"
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
269
frameworks/native/rdb/src/trans_db.cpp
Normal file
269
frameworks/native/rdb/src/trans_db.cpp
Normal 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
|
32
frameworks/native/rdb/src/transaction.cpp
Normal file
32
frameworks/native/rdb/src/transaction.cpp
Normal 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;
|
||||
}
|
||||
}
|
290
frameworks/native/rdb/src/transaction_impl.cpp
Normal file
290
frameworks/native/rdb/src/transaction_impl.cpp
Normal 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);
|
||||
}
|
||||
}
|
@ -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
|
||||
|
@ -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" ]
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
183
interfaces/inner_api/rdb/include/transaction.h
Normal file
183
interfaces/inner_api/rdb/include/transaction.h
Normal 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
|
@ -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;
|
||||
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
||||
|
@ -119,6 +119,7 @@ describe('rdbStoreQueryByCursorTest', function () {
|
||||
});
|
||||
done();
|
||||
})
|
||||
|
||||
/**
|
||||
* @tc.name query with cursor
|
||||
* @tc.number SUB_DDM_AppDataFWK_JSRDB_QUERY_WITH_CURSOR_0002
|
||||
|
@ -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
|
||||
|
@ -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*************");
|
||||
})
|
1986
test/js/relationalstore/unittest/src/RdbStoreTransJsunit.test.js
Normal file
1986
test/js/relationalstore/unittest/src/RdbStoreTransJsunit.test.js
Normal file
File diff suppressed because it is too large
Load Diff
1700
test/js/relationalstore/unittest/src/RdbStoreTransaction.test.js
Normal file
1700
test/js/relationalstore/unittest/src/RdbStoreTransaction.test.js
Normal file
File diff suppressed because it is too large
Load Diff
@ -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" ]
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
1197
test/native/rdb/unittest/rdb_trans_db_test.cpp
Normal file
1197
test/native/rdb/unittest/rdb_trans_db_test.cpp
Normal file
File diff suppressed because it is too large
Load Diff
@ -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
|
||||
|
@ -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);
|
||||
}
|
391
test/native/rdb/unittest/transaction_test.cpp
Normal file
391
test/native/rdb/unittest/transaction_test.cpp
Normal 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);
|
||||
}
|
Loading…
Reference in New Issue
Block a user