From 785792dc57cb1174e041d3677bd28a967b06255d Mon Sep 17 00:00:00 2001 From: Sven Wang Date: Wed, 15 Mar 2023 13:04:17 +0800 Subject: [PATCH 01/44] add cloud Signed-off-by: Sven Wang --- .../framework/include/store/common_store.h | 38 ++++++++++++++ .../framework/include/store/cursor.h | 52 +++++++++++++++++++ .../framework/store/cursor.cpp | 16 ++++++ .../service/CMakeLists.txt | 2 + .../service/cloud/cloud_service_impl.cpp | 16 ++++++ .../service/cloud/cloud_service_impl.h | 23 ++++++++ .../cloud_data/include/cloud_data_feature.h | 23 ++++++++ 7 files changed, 170 insertions(+) create mode 100644 datamgr_service/services/distributeddataservice/framework/include/store/common_store.h create mode 100644 datamgr_service/services/distributeddataservice/framework/include/store/cursor.h create mode 100644 datamgr_service/services/distributeddataservice/framework/store/cursor.cpp create mode 100644 datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.cpp create mode 100644 datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.h create mode 100644 datamgr_service/services/distributeddataservice/service/cloud_data/include/cloud_data_feature.h diff --git a/datamgr_service/services/distributeddataservice/framework/include/store/common_store.h b/datamgr_service/services/distributeddataservice/framework/include/store/common_store.h new file mode 100644 index 00000000..ac388225 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/framework/include/store/common_store.h @@ -0,0 +1,38 @@ +/* + * 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_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_STORE_INNER_DB_STORE_H +#define OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_STORE_INNER_DB_STORE_H +#include "store/cursor.h" +namespace OHOS::DistributedData { +class CommonStore { +public: + struct Asset { + std::string name; + }; + using Asset = struct Asset; + using Assets = std::vector; + using Bytes = std::vector; + using DBValue = std::variant; + using Cursor = DistributedDB::ResultSet; + virtual ~CommonStore() = 0; + int32_t Insert(const std::string &table, std::map &&values) = 0; + int32_t Update(const std::string &table, const std::string &sql, std::map &&values) = 0; + int32_t Delete(const std::string &table, const std::string &sql, std::vector &&args) = 0; + std::shared_ptr Query(const std::string &table, const std::string &sql, std::vector &&args) = 0; +}; +} + +#endif // OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_STORE_INNER_DB_STORE_H diff --git a/datamgr_service/services/distributeddataservice/framework/include/store/cursor.h b/datamgr_service/services/distributeddataservice/framework/include/store/cursor.h new file mode 100644 index 00000000..aceef9aa --- /dev/null +++ b/datamgr_service/services/distributeddataservice/framework/include/store/cursor.h @@ -0,0 +1,52 @@ +/* + * 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_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_STORE_CURSOR_H +#define OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_STORE_CURSOR_H +namespace OHOS::DistributedData { +class Cursor { +public: + struct Asset { + int32_t version; + std::string name; + }; + using Asset = struct Asset; + using Assets = std::vector; + using Bytes = std::vector; + using DBValue = std::variant; + virtual ~Cursor() {}; + + virtual int32_t GetCount() const = 0; + + virtual int32_t MoveToFirst() = 0; + + virtual int32_t MoveToNext() = 0; + + virtual int32_t Close() = 0; + + virtual int32_t GetEntry(Entry &entry) const = 0; + + virtual int32_t GetColumnNames(std::vector &names) const = 0; + + virtual int32_t GetColumnName(int32_t col, std::string &name) const = 0; + + virtual int32_t GetColumnType(int32_t col) const = 0; + + virtual int32_t Get(int32_t col, DBValue &value) const = 0; + + virtual int32_t GetRow(std::map &data) const = 0; +}; +} +#endif // OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_STORE_CURSOR_H diff --git a/datamgr_service/services/distributeddataservice/framework/store/cursor.cpp b/datamgr_service/services/distributeddataservice/framework/store/cursor.cpp new file mode 100644 index 00000000..6e7d46db --- /dev/null +++ b/datamgr_service/services/distributeddataservice/framework/store/cursor.cpp @@ -0,0 +1,16 @@ +/* + * 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. + */ + +#include "cursor.h" diff --git a/datamgr_service/services/distributeddataservice/service/CMakeLists.txt b/datamgr_service/services/distributeddataservice/service/CMakeLists.txt index a90fab7b..bd77fdef 100644 --- a/datamgr_service/services/distributeddataservice/service/CMakeLists.txt +++ b/datamgr_service/services/distributeddataservice/service/CMakeLists.txt @@ -22,6 +22,7 @@ aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/matrix/src serviceSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/object serviceSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/data_share serviceSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/permission/src serviceSrc) +aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/cloud/src serviceSrc) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/backup/include) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/config/include) @@ -30,6 +31,7 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR}/bootstrap/include) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/directory/include) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/permission/include) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/matrix/include) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/cloud/include) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/rdb) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/kvdb) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../framework/include) diff --git a/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.cpp b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.cpp new file mode 100644 index 00000000..f3e4990d --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.cpp @@ -0,0 +1,16 @@ +/* + * 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. + */ + +#include "cloud_service_impl.h" diff --git a/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.h b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.h new file mode 100644 index 00000000..a798d70e --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.h @@ -0,0 +1,23 @@ +/* + * 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_DISTRIBUTED_DATA_SERVICES_CLOUD_CLOUD_DATA_FEATURE_H +#define OHOS_DISTRIBUTED_DATA_SERVICES_CLOUD_CLOUD_DATA_FEATURE_H +namespace OHOS::DistributedData { +class CloudServiceImpl : public { +}; +} // namespace OHOS::DistributedData + +#endif // OHOS_DISTRIBUTED_DATA_SERVICES_CLOUD_CLOUD_DATA_FEATURE_H diff --git a/datamgr_service/services/distributeddataservice/service/cloud_data/include/cloud_data_feature.h b/datamgr_service/services/distributeddataservice/service/cloud_data/include/cloud_data_feature.h new file mode 100644 index 00000000..f2e628d0 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/cloud_data/include/cloud_data_feature.h @@ -0,0 +1,23 @@ +/* + * 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_DISTRIBUTED_DATA_DATAMGR_SERVICE_SERVICES_DISTRIBUTEDDATASERVICE_SERVICE_CLOUD_DATA_CLOUD_DATA_FEATURE_H +#define OHOS_DISTRIBUTED_DATA_DATAMGR_SERVICE_SERVICES_DISTRIBUTEDDATASERVICE_SERVICE_CLOUD_DATA_CLOUD_DATA_FEATURE_H + +class CloudDataFeature { + +}; + +#endif // OHOS_DISTRIBUTED_DATA_DATAMGR_SERVICE_SERVICES_DISTRIBUTEDDATASERVICE_SERVICE_CLOUD_DATA_CLOUD_DATA_FEATURE_H -- Gitee From 09bfe6a5fa2602b2f8aec212535f1f77ede89a85 Mon Sep 17 00:00:00 2001 From: Sven Wang Date: Tue, 28 Mar 2023 20:36:35 +0800 Subject: [PATCH 02/44] update Signed-off-by: Sven Wang --- .../framework/CMakeLists.txt | 6 +- .../framework/cloud/asset_loader.cpp | 16 ++++ .../framework/cloud/cloud_db.cpp | 16 ++++ .../framework/cloud/cloud_info.cpp | 70 ++++++++++++++++ .../framework/cloud/cloud_server.cpp | 32 ++++++++ .../framework/cloud/schema_meta.cpp | 77 ++++++++++++++++++ .../framework/include/cloud/asset_loader.h | 27 +++++++ .../framework/include/cloud/cloud_db.h | 27 +++++++ .../framework/include/cloud/cloud_info.h | 49 ++++++++++++ .../framework/include/cloud/cloud_server.h | 38 +++++++++ .../framework/include/cloud/schema_meta.h | 52 ++++++++++++ .../include/store/asset.h} | 18 +++-- .../framework/include/store/cursor.h | 23 +++--- .../store/{common_store.h => general_store.h} | 28 +++---- .../framework/store/asset.cpp | 16 ++++ .../framework/store/cursor.cpp | 2 +- .../service/CMakeLists.txt | 4 +- .../service/cloud/cloud_service.h | 47 +++++++++++ .../service/cloud/cloud_service_impl.h | 11 +-- .../service/cloud/cloud_service_stub.cpp | 79 +++++++++++++++++++ .../service/cloud/cloud_service_stub.h | 37 +++++++++ kv_store/frameworks/common/log_print.h | 21 +++-- 22 files changed, 647 insertions(+), 49 deletions(-) create mode 100644 datamgr_service/services/distributeddataservice/framework/cloud/asset_loader.cpp create mode 100644 datamgr_service/services/distributeddataservice/framework/cloud/cloud_db.cpp create mode 100644 datamgr_service/services/distributeddataservice/framework/cloud/cloud_info.cpp create mode 100644 datamgr_service/services/distributeddataservice/framework/cloud/cloud_server.cpp create mode 100644 datamgr_service/services/distributeddataservice/framework/cloud/schema_meta.cpp create mode 100644 datamgr_service/services/distributeddataservice/framework/include/cloud/asset_loader.h create mode 100644 datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_db.h create mode 100644 datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_info.h create mode 100644 datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_server.h create mode 100644 datamgr_service/services/distributeddataservice/framework/include/cloud/schema_meta.h rename datamgr_service/services/distributeddataservice/{service/cloud_data/include/cloud_data_feature.h => framework/include/store/asset.h} (61%) rename datamgr_service/services/distributeddataservice/framework/include/store/{common_store.h => general_store.h} (56%) create mode 100644 datamgr_service/services/distributeddataservice/framework/store/asset.cpp create mode 100644 datamgr_service/services/distributeddataservice/service/cloud/cloud_service.h create mode 100644 datamgr_service/services/distributeddataservice/service/cloud/cloud_service_stub.cpp create mode 100644 datamgr_service/services/distributeddataservice/service/cloud/cloud_service_stub.h diff --git a/datamgr_service/services/distributeddataservice/framework/CMakeLists.txt b/datamgr_service/services/distributeddataservice/framework/CMakeLists.txt index 85c38e69..3c76dea5 100644 --- a/datamgr_service/services/distributeddataservice/framework/CMakeLists.txt +++ b/datamgr_service/services/distributeddataservice/framework/CMakeLists.txt @@ -12,10 +12,12 @@ set(MOCK_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../../../mock") set(KV_STORE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../../../kv_store") aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/backuprule svcFwkSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/checker svcFwkSrc) -aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/metadata svcFwkSrc) +aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/cloud svcFwkSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/eventcenter svcFwkSrc) -aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/serializable svcFwkSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/feature svcFwkSrc) +aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/metadata svcFwkSrc) +aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/serializable svcFwkSrc) +aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/store svcFwkSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/utils svcFwkSrc) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../adapter/include) diff --git a/datamgr_service/services/distributeddataservice/framework/cloud/asset_loader.cpp b/datamgr_service/services/distributeddataservice/framework/cloud/asset_loader.cpp new file mode 100644 index 00000000..a1f54cc1 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/framework/cloud/asset_loader.cpp @@ -0,0 +1,16 @@ +/* + * 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. + */ + +#include "asset_loader.h" diff --git a/datamgr_service/services/distributeddataservice/framework/cloud/cloud_db.cpp b/datamgr_service/services/distributeddataservice/framework/cloud/cloud_db.cpp new file mode 100644 index 00000000..65bb7b3e --- /dev/null +++ b/datamgr_service/services/distributeddataservice/framework/cloud/cloud_db.cpp @@ -0,0 +1,16 @@ +/* + * 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. + */ + +#include "cloud/cloud_db.h" diff --git a/datamgr_service/services/distributeddataservice/framework/cloud/cloud_info.cpp b/datamgr_service/services/distributeddataservice/framework/cloud/cloud_info.cpp new file mode 100644 index 00000000..17d7b1f1 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/framework/cloud/cloud_info.cpp @@ -0,0 +1,70 @@ +/* + * 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. + */ + +#include "cloud/cloud_info.h" +namespace OHOS::DistributedData { +bool CloudInfo::Marshal(Serializable::json &node) const +{ + SetValue(node[GET_NAME(user)], user); + SetValue(node[GET_NAME(id)], id); + SetValue(node[GET_NAME(totalSpace)], totalSpace); + SetValue(node[GET_NAME(remainSpace)], remainSpace); + SetValue(node[GET_NAME(enableCloud)], enableCloud); + SetValue(node[GET_NAME(apps)], apps); + return true; +} + +bool CloudInfo::Unmarshal(const Serializable::json &node) +{ + GetValue(node, GET_NAME(user), user); + GetValue(node, GET_NAME(id), id); + GetValue(node, GET_NAME(totalSpace), totalSpace); + GetValue(node, GET_NAME(remainSpace), remainSpace); + GetValue(node, GET_NAME(enableCloud), enableCloud); + GetValue(node, GET_NAME(apps), apps); + return true; +} + +bool CloudInfo::AppInfo::Marshal(Serializable::json &node) const +{ + SetValue(node[GET_NAME(bundleName)], bundleName); + SetValue(node[GET_NAME(appId)], appId); + SetValue(node[GET_NAME(version)], version); + SetValue(node[GET_NAME(cloudSwitch)], cloudSwitch); + return true; +} + +bool CloudInfo::AppInfo::Unmarshal(const Serializable::json &node) +{ + GetValue(node, GET_NAME(bundleName), bundleName); + GetValue(node, GET_NAME(appId), appId); + GetValue(node, GET_NAME(version), version); + GetValue(node, GET_NAME(cloudSwitch), cloudSwitch); + return true; +} + +std::string CloudInfo::GetKey() const +{ + return std::string(); +} + +std::map CloudInfo::GetSchemaKey() const +{ + for (auto &app : apps) { + + } + return std::map(); +} +} // namespace OHOS::DistributedData \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/framework/cloud/cloud_server.cpp b/datamgr_service/services/distributeddataservice/framework/cloud/cloud_server.cpp new file mode 100644 index 00000000..48f1ce76 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/framework/cloud/cloud_server.cpp @@ -0,0 +1,32 @@ +/* + * 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. + */ + +#include "cloud/cloud_server.h" +namespace OHOS::DistributedData { +CloudServer *CloudServer::instance_ = nullptr; +CloudServer *CloudServer::GetInstance() +{ + return instance_; +} + +bool CloudServer::RegisterCloudInstance(CloudServer *instance) +{ + if (instance_ != nullptr) { + return false; + } + instance_ = instance; + return true; +} +} // namespace OHOS::DistributedData \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/framework/cloud/schema_meta.cpp b/datamgr_service/services/distributeddataservice/framework/cloud/schema_meta.cpp new file mode 100644 index 00000000..8fe8f41b --- /dev/null +++ b/datamgr_service/services/distributeddataservice/framework/cloud/schema_meta.cpp @@ -0,0 +1,77 @@ +/* + * 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. + */ + +#include "cloud/schema_meta.h" +namespace OHOS::DistributedData { +bool SchemaMeta::Marshal(Serializable::json &node) const +{ + SetValue(node[GET_NAME(version)], version); + SetValue(node[GET_NAME(databases)], databases); + return true; +} + +bool SchemaMeta::Unmarshal(const Serializable::json &node) +{ + GetValue(node, GET_NAME(version), version); + GetValue(node, GET_NAME(databases), databases); + return true; +} + +bool SchemaMeta::Database::Marshal(Serializable::json &node) const +{ + SetValue(node[GET_NAME(name)], name); + SetValue(node[GET_NAME(tables)], tables); + return true; +} + +bool SchemaMeta::Database::Unmarshal(const Serializable::json &node) +{ + GetValue(node, GET_NAME(name), name); + GetValue(node, GET_NAME(tables), tables); + return true; +} + +bool SchemaMeta::Table::Marshal(Serializable::json &node) const +{ + SetValue(node[GET_NAME(name)], name); + SetValue(node[GET_NAME(type)], type); + return true; +} + +bool SchemaMeta::Table::Unmarshal(const Serializable::json &node) +{ + GetValue(node, GET_NAME(name), name); + GetValue(node, GET_NAME(type), type); + return true; +} + +bool SchemaMeta::Field::Marshal(Serializable::json &node) const +{ + SetValue(node[GET_NAME(colName)], colName); + SetValue(node[GET_NAME(type)], type); + SetValue(node[GET_NAME(primary)], primary); + SetValue(node[GET_NAME(nullable)], nullable); + return true; +} + +bool SchemaMeta::Field::Unmarshal(const Serializable::json &node) +{ + GetValue(node, GET_NAME(colName), colName); + GetValue(node, GET_NAME(type), type); + GetValue(node, GET_NAME(primary), primary); + GetValue(node, GET_NAME(nullable), nullable); + return true; +} +} // namespace OHOS::DistributedData \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/framework/include/cloud/asset_loader.h b/datamgr_service/services/distributeddataservice/framework/include/cloud/asset_loader.h new file mode 100644 index 00000000..eb8b227c --- /dev/null +++ b/datamgr_service/services/distributeddataservice/framework/include/cloud/asset_loader.h @@ -0,0 +1,27 @@ +/* + * 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_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_CLOUD_ASSET_LOADER_H +#define OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_CLOUD_ASSET_LOADER_H +#include "store/asset.h" +namespace OHOS::DistributedData { +class AssetLoader { +public: + virtual ~AssetLoader() = 0; + virtual int32_t Upload(const Asset &asset) = 0; + virtual int32_t Download(Asset &asset) = 0; +}; +} // namespace OHOS::DistributedData +#endif // OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_CLOUD_ASSET_LOADER_H diff --git a/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_db.h b/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_db.h new file mode 100644 index 00000000..fddab369 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_db.h @@ -0,0 +1,27 @@ +/* + * 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_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_CLOUD_CLOUD_DB_H +#define OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_CLOUD_CLOUD_DB_H +#include "store/general_store.h" +namespace OHOS::DistributedData { +class CloudDB : public GeneralStore { +public: + virtual int32_t Lock() = 0; + virtual int32_t Unlock() = 0; + virtual int32_t Flush() = 0; +}; +} // namespace OHOS::DistributedData +#endif // OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_CLOUD_CLOUD_DB_H diff --git a/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_info.h b/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_info.h new file mode 100644 index 00000000..22f37cbb --- /dev/null +++ b/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_info.h @@ -0,0 +1,49 @@ +/* + * 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_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_CLOUD_CLOUD_INFO_H +#define OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_CLOUD_CLOUD_INFO_H +#include "serializable/serializable.h" +namespace OHOS::DistributedData { +class API_EXPORT CloudInfo final : public Serializable { +public: + struct API_EXPORT AppInfo final : public Serializable { + std::string bundleName; + std::string appId; + uint64_t version; + bool cloudSwitch = false; + + bool Marshal(json &node) const override; + bool Unmarshal(const json &node) override; + }; + int32_t user = 0; + std::string id; + uint64_t totalSpace = 0; + uint64_t remainSpace = 0; + bool enableCloud = false; + std::vector apps; + + std::string GetKey() const; + std::map GetSchemaKey() const; + + bool Marshal(json &node) const override; + bool Unmarshal(const json &node) override; + +private: + static constexpr const char *INFO_PREFIX = "CLOUD_INFO"; + static constexpr const char *SCHEMA_PREFIX = "CLOUD_SCHEMA"; +}; +} +#endif // OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_CLOUD_CLOUD_INFO_H diff --git a/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_server.h b/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_server.h new file mode 100644 index 00000000..f9c373c5 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_server.h @@ -0,0 +1,38 @@ +/* + * 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_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_CLOUD_CLOUD_SERVER_H +#define OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_CLOUD_CLOUD_SERVER_H +#include "cloud/asset_loader.h" +#include "cloud/cloud_db.h" +#include "cloud/cloud_info.h" +#include "cloud/schema_meta.h" +#include "visibility.h" +namespace OHOS::DistributedData { +class CloudServer { +public: + API_EXPORT static CloudServer *GetInstance(); + API_EXPORT static bool RegisterCloudInstance(CloudServer *instance); + virtual CloudInfo GetServerInfo(int32_t userId) = 0; + virtual SchemaMeta GetAppSchema(int32_t userId, const std::string &bundleName) = 0; + virtual std::shared_ptr ConnectAssetLoader(uint32_t tokenId, const std::string &cloudId) = 0; + virtual std::shared_ptr ConnectCloudDB(uint32_t tokenId, const std::string &cloudId, + const std::string &dbName) = 0; + +private: + static CloudServer *instance_; +}; +} // namespace OHOS::DistributedData +#endif // OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_CLOUD_CLOUD_SERVER_H diff --git a/datamgr_service/services/distributeddataservice/framework/include/cloud/schema_meta.h b/datamgr_service/services/distributeddataservice/framework/include/cloud/schema_meta.h new file mode 100644 index 00000000..d2fd0701 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/framework/include/cloud/schema_meta.h @@ -0,0 +1,52 @@ +/* + * 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_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_CLOUD_SCHEMA_META_H +#define OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_CLOUD_SCHEMA_META_H +#include "serializable/serializable.h" +namespace OHOS::DistributedData { +class API_EXPORT SchemaMeta final : public Serializable { +public: + struct API_EXPORT Field final : public Serializable { + std::string colName; + std::string type; + bool primary = false; + bool nullable = true; + bool Marshal(json &node) const override; + bool Unmarshal(const json &node) override; + }; + + struct API_EXPORT Table final : public Serializable { + std::string name; + std::vector type; + bool Marshal(json &node) const override; + bool Unmarshal(const json &node) override; + }; + + struct API_EXPORT Database final : public Serializable { + std::string name; + std::vector tables; + + bool Marshal(json &node) const override; + bool Unmarshal(const json &node) override; + }; + int32_t version = 0; + std::vector databases; + + bool Marshal(json &node) const override; + bool Unmarshal(const json &node) override; +}; +} // namespace OHOS::DistributedData +#endif // OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_CLOUD_SCHEMA_META_H diff --git a/datamgr_service/services/distributeddataservice/service/cloud_data/include/cloud_data_feature.h b/datamgr_service/services/distributeddataservice/framework/include/store/asset.h similarity index 61% rename from datamgr_service/services/distributeddataservice/service/cloud_data/include/cloud_data_feature.h rename to datamgr_service/services/distributeddataservice/framework/include/store/asset.h index f2e628d0..8bc758d9 100644 --- a/datamgr_service/services/distributeddataservice/service/cloud_data/include/cloud_data_feature.h +++ b/datamgr_service/services/distributeddataservice/framework/include/store/asset.h @@ -13,11 +13,15 @@ * limitations under the License. */ -#ifndef OHOS_DISTRIBUTED_DATA_DATAMGR_SERVICE_SERVICES_DISTRIBUTEDDATASERVICE_SERVICE_CLOUD_DATA_CLOUD_DATA_FEATURE_H -#define OHOS_DISTRIBUTED_DATA_DATAMGR_SERVICE_SERVICES_DISTRIBUTEDDATASERVICE_SERVICE_CLOUD_DATA_CLOUD_DATA_FEATURE_H - -class CloudDataFeature { - +#ifndef OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_STORE_INNER_ASSET_H +#define OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_STORE_INNER_ASSET_H +#include +namespace OHOS::DistributedData { +struct Asset { + uint32_t version; + std::string name; + std::string modifyTime; + std::string size; }; - -#endif // OHOS_DISTRIBUTED_DATA_DATAMGR_SERVICE_SERVICES_DISTRIBUTEDDATASERVICE_SERVICE_CLOUD_DATA_CLOUD_DATA_FEATURE_H +} +#endif // OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_STORE_INNER_ASSET_H diff --git a/datamgr_service/services/distributeddataservice/framework/include/store/cursor.h b/datamgr_service/services/distributeddataservice/framework/include/store/cursor.h index aceef9aa..e683542d 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/store/cursor.h +++ b/datamgr_service/services/distributeddataservice/framework/include/store/cursor.h @@ -15,18 +15,19 @@ #ifndef OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_STORE_CURSOR_H #define OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_STORE_CURSOR_H +#include +#include +#include + +#include "store/asset.h" namespace OHOS::DistributedData { class Cursor { public: - struct Asset { - int32_t version; - std::string name; - }; - using Asset = struct Asset; using Assets = std::vector; using Bytes = std::vector; - using DBValue = std::variant; - virtual ~Cursor() {}; + using Value = std::variant; + using VBucket = std::map; + virtual ~Cursor(){}; virtual int32_t GetCount() const = 0; @@ -36,7 +37,7 @@ public: virtual int32_t Close() = 0; - virtual int32_t GetEntry(Entry &entry) const = 0; + virtual int32_t GetEntry(VBucket &entry) const = 0; virtual int32_t GetColumnNames(std::vector &names) const = 0; @@ -44,9 +45,9 @@ public: virtual int32_t GetColumnType(int32_t col) const = 0; - virtual int32_t Get(int32_t col, DBValue &value) const = 0; + virtual int32_t Get(int32_t col, Value &value) const = 0; - virtual int32_t GetRow(std::map &data) const = 0; + virtual int32_t GetRow(VBucket &data) const = 0; }; -} +} // namespace OHOS::DistributedData #endif // OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_STORE_CURSOR_H diff --git a/datamgr_service/services/distributeddataservice/framework/include/store/common_store.h b/datamgr_service/services/distributeddataservice/framework/include/store/general_store.h similarity index 56% rename from datamgr_service/services/distributeddataservice/framework/include/store/common_store.h rename to datamgr_service/services/distributeddataservice/framework/include/store/general_store.h index ac388225..f7f56229 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/store/common_store.h +++ b/datamgr_service/services/distributeddataservice/framework/include/store/general_store.h @@ -15,24 +15,24 @@ #ifndef OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_STORE_INNER_DB_STORE_H #define OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_STORE_INNER_DB_STORE_H +#include + +#include "store/asset.h" #include "store/cursor.h" namespace OHOS::DistributedData { -class CommonStore { +class GeneralStore { public: - struct Asset { - std::string name; - }; - using Asset = struct Asset; using Assets = std::vector; using Bytes = std::vector; - using DBValue = std::variant; - using Cursor = DistributedDB::ResultSet; - virtual ~CommonStore() = 0; - int32_t Insert(const std::string &table, std::map &&values) = 0; - int32_t Update(const std::string &table, const std::string &sql, std::map &&values) = 0; - int32_t Delete(const std::string &table, const std::string &sql, std::vector &&args) = 0; - std::shared_ptr Query(const std::string &table, const std::string &sql, std::vector &&args) = 0; + using Value = std::variant; + using Values = std::vector; + using VBucket = std::map; + virtual ~GeneralStore() = 0; + virtual int32_t Close() = 0; + virtual int32_t Insert(const std::string &table, VBucket &&values) = 0; + virtual int32_t Update(const std::string &table, const std::string &sql, VBucket &&values) = 0; + virtual int32_t Delete(const std::string &table, const std::string &sql, Values &&args) = 0; + virtual std::shared_ptr Query(const std::string &table, const std::string &sql, Values &&args) = 0; }; -} - +} // namespace OHOS::DistributedData #endif // OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_STORE_INNER_DB_STORE_H diff --git a/datamgr_service/services/distributeddataservice/framework/store/asset.cpp b/datamgr_service/services/distributeddataservice/framework/store/asset.cpp new file mode 100644 index 00000000..4fc843b6 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/framework/store/asset.cpp @@ -0,0 +1,16 @@ +/* + * 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. + */ + +#include "store/asset.h" diff --git a/datamgr_service/services/distributeddataservice/framework/store/cursor.cpp b/datamgr_service/services/distributeddataservice/framework/store/cursor.cpp index 6e7d46db..3ac0d6dc 100644 --- a/datamgr_service/services/distributeddataservice/framework/store/cursor.cpp +++ b/datamgr_service/services/distributeddataservice/framework/store/cursor.cpp @@ -13,4 +13,4 @@ * limitations under the License. */ -#include "cursor.h" +#include "store/cursor.h" diff --git a/datamgr_service/services/distributeddataservice/service/CMakeLists.txt b/datamgr_service/services/distributeddataservice/service/CMakeLists.txt index bd77fdef..8e04aa87 100644 --- a/datamgr_service/services/distributeddataservice/service/CMakeLists.txt +++ b/datamgr_service/services/distributeddataservice/service/CMakeLists.txt @@ -12,6 +12,7 @@ set(MOCK_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../../../mock") set(KV_STORE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../../../kv_store") aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/backup/src serviceSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/bootstrap/src serviceSrc) +aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/cloud serviceSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/config/src serviceSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/config/src/model serviceSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/directory/src serviceSrc) @@ -22,7 +23,6 @@ aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/matrix/src serviceSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/object serviceSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/data_share serviceSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/permission/src serviceSrc) -aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/cloud/src serviceSrc) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/backup/include) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/config/include) @@ -31,7 +31,7 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR}/bootstrap/include) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/directory/include) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/permission/include) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/matrix/include) -include_directories(${CMAKE_CURRENT_SOURCE_DIR}/cloud/include) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/cloud) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/rdb) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/kvdb) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../framework/include) diff --git a/datamgr_service/services/distributeddataservice/service/cloud/cloud_service.h b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service.h new file mode 100644 index 00000000..f360b317 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service.h @@ -0,0 +1,47 @@ +/* + * 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_DISTRIBUTED_DATA_SERVICES_CLOUD_CLOUD_SERVICE_H +#define OHOS_DISTRIBUTED_DATA_SERVICES_CLOUD_CLOUD_SERVICE_H +#include +#include +#include +namespace OHOS::CloudData { +class CloudService { +public: + enum TransId : int32_t { + TRANS_HEAD, + TRANS_ENABLE_CLOUD = TRANS_HEAD, + TRANS_DISABLE_CLOUD, + TRANS_CHANGE_APP_SWITCH, + TRANS_CLEAN, + TRANS_NOTIFY_DATA_CHANGE, + TRANS_BUTT, + }; + enum Action : int32_t { + CLEAR_CLOUD_INFO, + CLEAR_CLOUD_DATA_AND_INFO, + CLEAR_CLOUD_BUTT + }; + virtual ~CloudService() = 0; + virtual int32_t EnableCloud(const std::string &id, const std::map &switches) = 0; + virtual int32_t DisableCloud(const std::string &id) = 0; + virtual int32_t ChangeAppSwitch(const std::string &id, const std::string &bundleName, bool isOn) = 0; + virtual int32_t Clean(const std::string &id, const std::map &actions) = 0; + virtual int32_t NotifyDataChange(const std::string &id, const std::string &bundleName) = 0; +}; +} // namespace OHOS::CloudData + +#endif // OHOS_DISTRIBUTED_DATA_SERVICES_CLOUD_CLOUD_SERVICE_H diff --git a/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.h b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.h index a798d70e..50644cec 100644 --- a/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.h +++ b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.h @@ -13,11 +13,12 @@ * limitations under the License. */ -#ifndef OHOS_DISTRIBUTED_DATA_SERVICES_CLOUD_CLOUD_DATA_FEATURE_H -#define OHOS_DISTRIBUTED_DATA_SERVICES_CLOUD_CLOUD_DATA_FEATURE_H -namespace OHOS::DistributedData { -class CloudServiceImpl : public { +#ifndef OHOS_DISTRIBUTED_DATA_SERVICES_CLOUD_CLOUD_SERVICE_IMPL_H +#define OHOS_DISTRIBUTED_DATA_SERVICES_CLOUD_CLOUD_SERVICE_IMPL_H +#include "cloud_service_stub.h" +namespace OHOS::CloudData { +class CloudServiceImpl : public CloudServiceStub { }; } // namespace OHOS::DistributedData -#endif // OHOS_DISTRIBUTED_DATA_SERVICES_CLOUD_CLOUD_DATA_FEATURE_H +#endif // OHOS_DISTRIBUTED_DATA_SERVICES_CLOUD_CLOUD_SERVICE_IMPL_H diff --git a/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_stub.cpp b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_stub.cpp new file mode 100644 index 00000000..de682439 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_stub.cpp @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#define LOG_TAG "CloudServiceStub" +#include "cloud_service_stub.h" + +#include + +#include "ipc_skeleton.h" +#include "log_print.h" +#include "utils/anonymous.h" +namespace OHOS::CloudData { +using namespace DistributedData; +const CloudServiceStub::Handler CloudServiceStub::HANDLERS[TRANS_BUTT] = { + &CloudServiceStub::EnableCloud, + &CloudServiceStub::DisableCloud, + &CloudServiceStub::ChangeAppSwitch, + &CloudServiceStub::Clean, + &CloudServiceStub::NotifyDataChange, +}; + +int CloudServiceStub::OnRemoteRequest(uint32_t code, OHOS::MessageParcel &data, OHOS::MessageParcel &reply) +{ + ZLOGI("code:%{public}u callingPid:%{public}u", code, IPCSkeleton::GetCallingPid()); + std::u16string local = CloudServiceStub::GetDescriptor(); + std::u16string remote = data.ReadInterfaceToken(); + if (local != remote) { + ZLOGE("local is not equal to remote"); + return -1; + } + + if (TRANS_HEAD > code || code >= TRANS_BUTT || HANDLERS[code] == nullptr) { + ZLOGE("not support code:%{public}u, BUTT:%{public}d", code, TRANS_BUTT); + return -1; + } + std::string id; + if (!ITypesUtil::Unmarshal(data, id)) { + ZLOGE("Unmarshal id:%{public}s", Anonymous::Change(id).c_str()); + return IPC_STUB_INVALID_DATA_ERR; + } + return (this->*HANDLERS[code])(id, data, reply); +} + +int32_t CloudServiceStub::EnableCloud(const std::string &id, MessageParcel &data, MessageParcel &reply) +{ + return 0; +} + +int32_t CloudServiceStub::DisableCloud(const std::string &id, MessageParcel &data, MessageParcel &reply) +{ + return 0; +} + +int32_t CloudServiceStub::ChangeAppSwitch(const std::string &id, MessageParcel &data, MessageParcel &reply) +{ + return 0; +} + +int32_t CloudServiceStub::Clean(const std::string &id, MessageParcel &data, MessageParcel &reply) +{ + return 0; +} + +int32_t CloudServiceStub::NotifyDataChange(const std::string &id, MessageParcel &data, MessageParcel &reply) +{ + return 0; +} +} // namespace OHOS::CloudData diff --git a/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_stub.h b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_stub.h new file mode 100644 index 00000000..32443fe2 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_stub.h @@ -0,0 +1,37 @@ +/* + * 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_DISTRIBUTED_DATA_SERVICES_CLOUD_CLOUD_SERVICE_STUB_H +#define OHOS_DISTRIBUTED_DATA_SERVICES_CLOUD_CLOUD_SERVICE_STUB_H +#include "cloud_service.h" +#include "feature/feature_system.h" +#include "iremote_broker.h" +namespace OHOS::CloudData { +class CloudServiceStub : public CloudService, public DistributedData::FeatureSystem::Feature { +public: + DECLARE_INTERFACE_DESCRIPTOR(u"OHOS.CloudData.CloudServer"); + int OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply) override; + +private: + using Handler = int32_t (CloudServiceStub::*)(const std::string &id, MessageParcel &data, MessageParcel &reply); + int32_t EnableCloud(const std::string &id, MessageParcel &data, MessageParcel &reply); + int32_t DisableCloud(const std::string &id, MessageParcel &data, MessageParcel &reply); + int32_t ChangeAppSwitch(const std::string &id, MessageParcel &data, MessageParcel &reply); + int32_t Clean(const std::string &id, MessageParcel &data, MessageParcel &reply); + int32_t NotifyDataChange(const std::string &id, MessageParcel &data, MessageParcel &reply); + static const Handler HANDLERS[TRANS_BUTT]; +}; +} // namespace OHOS::CloudData +#endif // OHOS_DISTRIBUTED_DATA_SERVICES_CLOUD_CLOUD_SERVICE_STUB_H diff --git a/kv_store/frameworks/common/log_print.h b/kv_store/frameworks/common/log_print.h index 717da466..274031b0 100644 --- a/kv_store/frameworks/common/log_print.h +++ b/kv_store/frameworks/common/log_print.h @@ -26,7 +26,7 @@ static inline OHOS::HiviewDFX::HiLogLabel LogLabel() { return { LOG_CORE, 0xD001610, "ZDDS" }; } -} // end namespace DistributesdKv +} // namespace DistributedKv namespace DistributedData { static inline OHOS::HiviewDFX::HiLogLabel LogLabel() @@ -42,6 +42,13 @@ static inline OHOS::HiviewDFX::HiLogLabel LogLabel() } } // end namespace DistributedKVStore +namespace CloudData { +static inline OHOS::HiviewDFX::HiLogLabel LogLabel() +{ + return { LOG_CORE, 0xD001613, "CLOUD" }; +} +} // end namespace CloudData + namespace AppDistributedKv { static inline OHOS::HiviewDFX::HiLogLabel LogLabel() { @@ -66,25 +73,25 @@ static inline OHOS::HiviewDFX::HiLogLabel LogLabel() namespace DistributedObject { static inline OHOS::HiviewDFX::HiLogLabel LogLabel() { - return { LOG_CORE, 0xD001654, "DOBJECT" }; + return { LOG_CORE, 0xD001654, "DOBJECT" }; } } // end namespace DistributedObject } // end namespace OHOS #define ZLOGD(fmt, ...) \ - OHOS::HiviewDFX::HiLog::Debug(LogLabel(), LOG_TAG "::%{public}s: " fmt, __FUNCTION__, ##__VA_ARGS__) + OHOS::HiviewDFX::HiLog::Debug(LogLabel(), LOG_TAG "::%{public}s: " fmt, __FUNCTION__, ##__VA_ARGS__) #define ZLOGI(fmt, ...) \ - OHOS::HiviewDFX::HiLog::Info(LogLabel(), LOG_TAG "::%{public}s: " fmt, __FUNCTION__, ##__VA_ARGS__) + OHOS::HiviewDFX::HiLog::Info(LogLabel(), LOG_TAG "::%{public}s: " fmt, __FUNCTION__, ##__VA_ARGS__) #define ZLOGW(fmt, ...) \ - OHOS::HiviewDFX::HiLog::Warn(LogLabel(), LOG_TAG "::%{public}s: " fmt, __FUNCTION__, ##__VA_ARGS__) + OHOS::HiviewDFX::HiLog::Warn(LogLabel(), LOG_TAG "::%{public}s: " fmt, __FUNCTION__, ##__VA_ARGS__) #define ZLOGE(fmt, ...) \ - OHOS::HiviewDFX::HiLog::Error(LogLabel(), LOG_TAG "::%{public}s: " fmt, __FUNCTION__, ##__VA_ARGS__) + OHOS::HiviewDFX::HiLog::Error(LogLabel(), LOG_TAG "::%{public}s: " fmt, __FUNCTION__, ##__VA_ARGS__) #else - #error // unknown system +#error // unknown system #endif #endif // DISTRIBUTEDDATA_LOG_PRINT_H -- Gitee From 7ab33a34655636018ec703c8245a5c6621baf525 Mon Sep 17 00:00:00 2001 From: Sven Wang Date: Tue, 28 Mar 2023 20:42:35 +0800 Subject: [PATCH 03/44] update Signed-off-by: Sven Wang --- .../framework/CMakeLists.txt | 6 +- .../framework/cloud/asset_loader.cpp | 16 ++++ .../framework/cloud/cloud_db.cpp | 16 ++++ .../framework/cloud/cloud_info.cpp | 70 ++++++++++++++++ .../framework/cloud/cloud_server.cpp | 32 ++++++++ .../framework/cloud/schema_meta.cpp | 77 ++++++++++++++++++ .../framework/include/cloud/asset_loader.h | 27 +++++++ .../framework/include/cloud/cloud_db.h | 27 +++++++ .../framework/include/cloud/cloud_info.h | 49 ++++++++++++ .../framework/include/cloud/cloud_server.h | 38 +++++++++ .../framework/include/cloud/schema_meta.h | 52 ++++++++++++ .../include/store/asset.h} | 18 +++-- .../framework/include/store/cursor.h | 23 +++--- .../store/{common_store.h => general_store.h} | 28 +++---- .../framework/store/asset.cpp | 16 ++++ .../framework/store/cursor.cpp | 2 +- .../service/CMakeLists.txt | 4 +- .../service/cloud/cloud_service.h | 47 +++++++++++ .../service/cloud/cloud_service_impl.h | 11 +-- .../service/cloud/cloud_service_stub.cpp | 79 +++++++++++++++++++ .../service/cloud/cloud_service_stub.h | 37 +++++++++ kv_store/frameworks/common/log_print.h | 21 +++-- 22 files changed, 647 insertions(+), 49 deletions(-) create mode 100644 datamgr_service/services/distributeddataservice/framework/cloud/asset_loader.cpp create mode 100644 datamgr_service/services/distributeddataservice/framework/cloud/cloud_db.cpp create mode 100644 datamgr_service/services/distributeddataservice/framework/cloud/cloud_info.cpp create mode 100644 datamgr_service/services/distributeddataservice/framework/cloud/cloud_server.cpp create mode 100644 datamgr_service/services/distributeddataservice/framework/cloud/schema_meta.cpp create mode 100644 datamgr_service/services/distributeddataservice/framework/include/cloud/asset_loader.h create mode 100644 datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_db.h create mode 100644 datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_info.h create mode 100644 datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_server.h create mode 100644 datamgr_service/services/distributeddataservice/framework/include/cloud/schema_meta.h rename datamgr_service/services/distributeddataservice/{service/cloud_data/include/cloud_data_feature.h => framework/include/store/asset.h} (61%) rename datamgr_service/services/distributeddataservice/framework/include/store/{common_store.h => general_store.h} (56%) create mode 100644 datamgr_service/services/distributeddataservice/framework/store/asset.cpp create mode 100644 datamgr_service/services/distributeddataservice/service/cloud/cloud_service.h create mode 100644 datamgr_service/services/distributeddataservice/service/cloud/cloud_service_stub.cpp create mode 100644 datamgr_service/services/distributeddataservice/service/cloud/cloud_service_stub.h diff --git a/datamgr_service/services/distributeddataservice/framework/CMakeLists.txt b/datamgr_service/services/distributeddataservice/framework/CMakeLists.txt index 85c38e69..3c76dea5 100644 --- a/datamgr_service/services/distributeddataservice/framework/CMakeLists.txt +++ b/datamgr_service/services/distributeddataservice/framework/CMakeLists.txt @@ -12,10 +12,12 @@ set(MOCK_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../../../mock") set(KV_STORE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../../../kv_store") aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/backuprule svcFwkSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/checker svcFwkSrc) -aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/metadata svcFwkSrc) +aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/cloud svcFwkSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/eventcenter svcFwkSrc) -aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/serializable svcFwkSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/feature svcFwkSrc) +aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/metadata svcFwkSrc) +aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/serializable svcFwkSrc) +aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/store svcFwkSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/utils svcFwkSrc) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../adapter/include) diff --git a/datamgr_service/services/distributeddataservice/framework/cloud/asset_loader.cpp b/datamgr_service/services/distributeddataservice/framework/cloud/asset_loader.cpp new file mode 100644 index 00000000..a1f54cc1 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/framework/cloud/asset_loader.cpp @@ -0,0 +1,16 @@ +/* + * 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. + */ + +#include "asset_loader.h" diff --git a/datamgr_service/services/distributeddataservice/framework/cloud/cloud_db.cpp b/datamgr_service/services/distributeddataservice/framework/cloud/cloud_db.cpp new file mode 100644 index 00000000..65bb7b3e --- /dev/null +++ b/datamgr_service/services/distributeddataservice/framework/cloud/cloud_db.cpp @@ -0,0 +1,16 @@ +/* + * 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. + */ + +#include "cloud/cloud_db.h" diff --git a/datamgr_service/services/distributeddataservice/framework/cloud/cloud_info.cpp b/datamgr_service/services/distributeddataservice/framework/cloud/cloud_info.cpp new file mode 100644 index 00000000..17d7b1f1 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/framework/cloud/cloud_info.cpp @@ -0,0 +1,70 @@ +/* + * 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. + */ + +#include "cloud/cloud_info.h" +namespace OHOS::DistributedData { +bool CloudInfo::Marshal(Serializable::json &node) const +{ + SetValue(node[GET_NAME(user)], user); + SetValue(node[GET_NAME(id)], id); + SetValue(node[GET_NAME(totalSpace)], totalSpace); + SetValue(node[GET_NAME(remainSpace)], remainSpace); + SetValue(node[GET_NAME(enableCloud)], enableCloud); + SetValue(node[GET_NAME(apps)], apps); + return true; +} + +bool CloudInfo::Unmarshal(const Serializable::json &node) +{ + GetValue(node, GET_NAME(user), user); + GetValue(node, GET_NAME(id), id); + GetValue(node, GET_NAME(totalSpace), totalSpace); + GetValue(node, GET_NAME(remainSpace), remainSpace); + GetValue(node, GET_NAME(enableCloud), enableCloud); + GetValue(node, GET_NAME(apps), apps); + return true; +} + +bool CloudInfo::AppInfo::Marshal(Serializable::json &node) const +{ + SetValue(node[GET_NAME(bundleName)], bundleName); + SetValue(node[GET_NAME(appId)], appId); + SetValue(node[GET_NAME(version)], version); + SetValue(node[GET_NAME(cloudSwitch)], cloudSwitch); + return true; +} + +bool CloudInfo::AppInfo::Unmarshal(const Serializable::json &node) +{ + GetValue(node, GET_NAME(bundleName), bundleName); + GetValue(node, GET_NAME(appId), appId); + GetValue(node, GET_NAME(version), version); + GetValue(node, GET_NAME(cloudSwitch), cloudSwitch); + return true; +} + +std::string CloudInfo::GetKey() const +{ + return std::string(); +} + +std::map CloudInfo::GetSchemaKey() const +{ + for (auto &app : apps) { + + } + return std::map(); +} +} // namespace OHOS::DistributedData \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/framework/cloud/cloud_server.cpp b/datamgr_service/services/distributeddataservice/framework/cloud/cloud_server.cpp new file mode 100644 index 00000000..48f1ce76 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/framework/cloud/cloud_server.cpp @@ -0,0 +1,32 @@ +/* + * 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. + */ + +#include "cloud/cloud_server.h" +namespace OHOS::DistributedData { +CloudServer *CloudServer::instance_ = nullptr; +CloudServer *CloudServer::GetInstance() +{ + return instance_; +} + +bool CloudServer::RegisterCloudInstance(CloudServer *instance) +{ + if (instance_ != nullptr) { + return false; + } + instance_ = instance; + return true; +} +} // namespace OHOS::DistributedData \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/framework/cloud/schema_meta.cpp b/datamgr_service/services/distributeddataservice/framework/cloud/schema_meta.cpp new file mode 100644 index 00000000..8fe8f41b --- /dev/null +++ b/datamgr_service/services/distributeddataservice/framework/cloud/schema_meta.cpp @@ -0,0 +1,77 @@ +/* + * 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. + */ + +#include "cloud/schema_meta.h" +namespace OHOS::DistributedData { +bool SchemaMeta::Marshal(Serializable::json &node) const +{ + SetValue(node[GET_NAME(version)], version); + SetValue(node[GET_NAME(databases)], databases); + return true; +} + +bool SchemaMeta::Unmarshal(const Serializable::json &node) +{ + GetValue(node, GET_NAME(version), version); + GetValue(node, GET_NAME(databases), databases); + return true; +} + +bool SchemaMeta::Database::Marshal(Serializable::json &node) const +{ + SetValue(node[GET_NAME(name)], name); + SetValue(node[GET_NAME(tables)], tables); + return true; +} + +bool SchemaMeta::Database::Unmarshal(const Serializable::json &node) +{ + GetValue(node, GET_NAME(name), name); + GetValue(node, GET_NAME(tables), tables); + return true; +} + +bool SchemaMeta::Table::Marshal(Serializable::json &node) const +{ + SetValue(node[GET_NAME(name)], name); + SetValue(node[GET_NAME(type)], type); + return true; +} + +bool SchemaMeta::Table::Unmarshal(const Serializable::json &node) +{ + GetValue(node, GET_NAME(name), name); + GetValue(node, GET_NAME(type), type); + return true; +} + +bool SchemaMeta::Field::Marshal(Serializable::json &node) const +{ + SetValue(node[GET_NAME(colName)], colName); + SetValue(node[GET_NAME(type)], type); + SetValue(node[GET_NAME(primary)], primary); + SetValue(node[GET_NAME(nullable)], nullable); + return true; +} + +bool SchemaMeta::Field::Unmarshal(const Serializable::json &node) +{ + GetValue(node, GET_NAME(colName), colName); + GetValue(node, GET_NAME(type), type); + GetValue(node, GET_NAME(primary), primary); + GetValue(node, GET_NAME(nullable), nullable); + return true; +} +} // namespace OHOS::DistributedData \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/framework/include/cloud/asset_loader.h b/datamgr_service/services/distributeddataservice/framework/include/cloud/asset_loader.h new file mode 100644 index 00000000..eb8b227c --- /dev/null +++ b/datamgr_service/services/distributeddataservice/framework/include/cloud/asset_loader.h @@ -0,0 +1,27 @@ +/* + * 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_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_CLOUD_ASSET_LOADER_H +#define OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_CLOUD_ASSET_LOADER_H +#include "store/asset.h" +namespace OHOS::DistributedData { +class AssetLoader { +public: + virtual ~AssetLoader() = 0; + virtual int32_t Upload(const Asset &asset) = 0; + virtual int32_t Download(Asset &asset) = 0; +}; +} // namespace OHOS::DistributedData +#endif // OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_CLOUD_ASSET_LOADER_H diff --git a/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_db.h b/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_db.h new file mode 100644 index 00000000..fddab369 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_db.h @@ -0,0 +1,27 @@ +/* + * 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_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_CLOUD_CLOUD_DB_H +#define OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_CLOUD_CLOUD_DB_H +#include "store/general_store.h" +namespace OHOS::DistributedData { +class CloudDB : public GeneralStore { +public: + virtual int32_t Lock() = 0; + virtual int32_t Unlock() = 0; + virtual int32_t Flush() = 0; +}; +} // namespace OHOS::DistributedData +#endif // OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_CLOUD_CLOUD_DB_H diff --git a/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_info.h b/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_info.h new file mode 100644 index 00000000..22f37cbb --- /dev/null +++ b/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_info.h @@ -0,0 +1,49 @@ +/* + * 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_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_CLOUD_CLOUD_INFO_H +#define OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_CLOUD_CLOUD_INFO_H +#include "serializable/serializable.h" +namespace OHOS::DistributedData { +class API_EXPORT CloudInfo final : public Serializable { +public: + struct API_EXPORT AppInfo final : public Serializable { + std::string bundleName; + std::string appId; + uint64_t version; + bool cloudSwitch = false; + + bool Marshal(json &node) const override; + bool Unmarshal(const json &node) override; + }; + int32_t user = 0; + std::string id; + uint64_t totalSpace = 0; + uint64_t remainSpace = 0; + bool enableCloud = false; + std::vector apps; + + std::string GetKey() const; + std::map GetSchemaKey() const; + + bool Marshal(json &node) const override; + bool Unmarshal(const json &node) override; + +private: + static constexpr const char *INFO_PREFIX = "CLOUD_INFO"; + static constexpr const char *SCHEMA_PREFIX = "CLOUD_SCHEMA"; +}; +} +#endif // OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_CLOUD_CLOUD_INFO_H diff --git a/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_server.h b/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_server.h new file mode 100644 index 00000000..f9c373c5 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_server.h @@ -0,0 +1,38 @@ +/* + * 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_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_CLOUD_CLOUD_SERVER_H +#define OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_CLOUD_CLOUD_SERVER_H +#include "cloud/asset_loader.h" +#include "cloud/cloud_db.h" +#include "cloud/cloud_info.h" +#include "cloud/schema_meta.h" +#include "visibility.h" +namespace OHOS::DistributedData { +class CloudServer { +public: + API_EXPORT static CloudServer *GetInstance(); + API_EXPORT static bool RegisterCloudInstance(CloudServer *instance); + virtual CloudInfo GetServerInfo(int32_t userId) = 0; + virtual SchemaMeta GetAppSchema(int32_t userId, const std::string &bundleName) = 0; + virtual std::shared_ptr ConnectAssetLoader(uint32_t tokenId, const std::string &cloudId) = 0; + virtual std::shared_ptr ConnectCloudDB(uint32_t tokenId, const std::string &cloudId, + const std::string &dbName) = 0; + +private: + static CloudServer *instance_; +}; +} // namespace OHOS::DistributedData +#endif // OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_CLOUD_CLOUD_SERVER_H diff --git a/datamgr_service/services/distributeddataservice/framework/include/cloud/schema_meta.h b/datamgr_service/services/distributeddataservice/framework/include/cloud/schema_meta.h new file mode 100644 index 00000000..d2fd0701 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/framework/include/cloud/schema_meta.h @@ -0,0 +1,52 @@ +/* + * 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_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_CLOUD_SCHEMA_META_H +#define OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_CLOUD_SCHEMA_META_H +#include "serializable/serializable.h" +namespace OHOS::DistributedData { +class API_EXPORT SchemaMeta final : public Serializable { +public: + struct API_EXPORT Field final : public Serializable { + std::string colName; + std::string type; + bool primary = false; + bool nullable = true; + bool Marshal(json &node) const override; + bool Unmarshal(const json &node) override; + }; + + struct API_EXPORT Table final : public Serializable { + std::string name; + std::vector type; + bool Marshal(json &node) const override; + bool Unmarshal(const json &node) override; + }; + + struct API_EXPORT Database final : public Serializable { + std::string name; + std::vector
tables; + + bool Marshal(json &node) const override; + bool Unmarshal(const json &node) override; + }; + int32_t version = 0; + std::vector databases; + + bool Marshal(json &node) const override; + bool Unmarshal(const json &node) override; +}; +} // namespace OHOS::DistributedData +#endif // OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_CLOUD_SCHEMA_META_H diff --git a/datamgr_service/services/distributeddataservice/service/cloud_data/include/cloud_data_feature.h b/datamgr_service/services/distributeddataservice/framework/include/store/asset.h similarity index 61% rename from datamgr_service/services/distributeddataservice/service/cloud_data/include/cloud_data_feature.h rename to datamgr_service/services/distributeddataservice/framework/include/store/asset.h index f2e628d0..8bc758d9 100644 --- a/datamgr_service/services/distributeddataservice/service/cloud_data/include/cloud_data_feature.h +++ b/datamgr_service/services/distributeddataservice/framework/include/store/asset.h @@ -13,11 +13,15 @@ * limitations under the License. */ -#ifndef OHOS_DISTRIBUTED_DATA_DATAMGR_SERVICE_SERVICES_DISTRIBUTEDDATASERVICE_SERVICE_CLOUD_DATA_CLOUD_DATA_FEATURE_H -#define OHOS_DISTRIBUTED_DATA_DATAMGR_SERVICE_SERVICES_DISTRIBUTEDDATASERVICE_SERVICE_CLOUD_DATA_CLOUD_DATA_FEATURE_H - -class CloudDataFeature { - +#ifndef OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_STORE_INNER_ASSET_H +#define OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_STORE_INNER_ASSET_H +#include +namespace OHOS::DistributedData { +struct Asset { + uint32_t version; + std::string name; + std::string modifyTime; + std::string size; }; - -#endif // OHOS_DISTRIBUTED_DATA_DATAMGR_SERVICE_SERVICES_DISTRIBUTEDDATASERVICE_SERVICE_CLOUD_DATA_CLOUD_DATA_FEATURE_H +} +#endif // OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_STORE_INNER_ASSET_H diff --git a/datamgr_service/services/distributeddataservice/framework/include/store/cursor.h b/datamgr_service/services/distributeddataservice/framework/include/store/cursor.h index aceef9aa..e683542d 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/store/cursor.h +++ b/datamgr_service/services/distributeddataservice/framework/include/store/cursor.h @@ -15,18 +15,19 @@ #ifndef OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_STORE_CURSOR_H #define OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_STORE_CURSOR_H +#include +#include +#include + +#include "store/asset.h" namespace OHOS::DistributedData { class Cursor { public: - struct Asset { - int32_t version; - std::string name; - }; - using Asset = struct Asset; using Assets = std::vector; using Bytes = std::vector; - using DBValue = std::variant; - virtual ~Cursor() {}; + using Value = std::variant; + using VBucket = std::map; + virtual ~Cursor(){}; virtual int32_t GetCount() const = 0; @@ -36,7 +37,7 @@ public: virtual int32_t Close() = 0; - virtual int32_t GetEntry(Entry &entry) const = 0; + virtual int32_t GetEntry(VBucket &entry) const = 0; virtual int32_t GetColumnNames(std::vector &names) const = 0; @@ -44,9 +45,9 @@ public: virtual int32_t GetColumnType(int32_t col) const = 0; - virtual int32_t Get(int32_t col, DBValue &value) const = 0; + virtual int32_t Get(int32_t col, Value &value) const = 0; - virtual int32_t GetRow(std::map &data) const = 0; + virtual int32_t GetRow(VBucket &data) const = 0; }; -} +} // namespace OHOS::DistributedData #endif // OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_STORE_CURSOR_H diff --git a/datamgr_service/services/distributeddataservice/framework/include/store/common_store.h b/datamgr_service/services/distributeddataservice/framework/include/store/general_store.h similarity index 56% rename from datamgr_service/services/distributeddataservice/framework/include/store/common_store.h rename to datamgr_service/services/distributeddataservice/framework/include/store/general_store.h index ac388225..f7f56229 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/store/common_store.h +++ b/datamgr_service/services/distributeddataservice/framework/include/store/general_store.h @@ -15,24 +15,24 @@ #ifndef OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_STORE_INNER_DB_STORE_H #define OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_STORE_INNER_DB_STORE_H +#include + +#include "store/asset.h" #include "store/cursor.h" namespace OHOS::DistributedData { -class CommonStore { +class GeneralStore { public: - struct Asset { - std::string name; - }; - using Asset = struct Asset; using Assets = std::vector; using Bytes = std::vector; - using DBValue = std::variant; - using Cursor = DistributedDB::ResultSet; - virtual ~CommonStore() = 0; - int32_t Insert(const std::string &table, std::map &&values) = 0; - int32_t Update(const std::string &table, const std::string &sql, std::map &&values) = 0; - int32_t Delete(const std::string &table, const std::string &sql, std::vector &&args) = 0; - std::shared_ptr Query(const std::string &table, const std::string &sql, std::vector &&args) = 0; + using Value = std::variant; + using Values = std::vector; + using VBucket = std::map; + virtual ~GeneralStore() = 0; + virtual int32_t Close() = 0; + virtual int32_t Insert(const std::string &table, VBucket &&values) = 0; + virtual int32_t Update(const std::string &table, const std::string &sql, VBucket &&values) = 0; + virtual int32_t Delete(const std::string &table, const std::string &sql, Values &&args) = 0; + virtual std::shared_ptr Query(const std::string &table, const std::string &sql, Values &&args) = 0; }; -} - +} // namespace OHOS::DistributedData #endif // OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_STORE_INNER_DB_STORE_H diff --git a/datamgr_service/services/distributeddataservice/framework/store/asset.cpp b/datamgr_service/services/distributeddataservice/framework/store/asset.cpp new file mode 100644 index 00000000..4fc843b6 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/framework/store/asset.cpp @@ -0,0 +1,16 @@ +/* + * 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. + */ + +#include "store/asset.h" diff --git a/datamgr_service/services/distributeddataservice/framework/store/cursor.cpp b/datamgr_service/services/distributeddataservice/framework/store/cursor.cpp index 6e7d46db..3ac0d6dc 100644 --- a/datamgr_service/services/distributeddataservice/framework/store/cursor.cpp +++ b/datamgr_service/services/distributeddataservice/framework/store/cursor.cpp @@ -13,4 +13,4 @@ * limitations under the License. */ -#include "cursor.h" +#include "store/cursor.h" diff --git a/datamgr_service/services/distributeddataservice/service/CMakeLists.txt b/datamgr_service/services/distributeddataservice/service/CMakeLists.txt index bd77fdef..8e04aa87 100644 --- a/datamgr_service/services/distributeddataservice/service/CMakeLists.txt +++ b/datamgr_service/services/distributeddataservice/service/CMakeLists.txt @@ -12,6 +12,7 @@ set(MOCK_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../../../mock") set(KV_STORE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../../../kv_store") aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/backup/src serviceSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/bootstrap/src serviceSrc) +aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/cloud serviceSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/config/src serviceSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/config/src/model serviceSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/directory/src serviceSrc) @@ -22,7 +23,6 @@ aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/matrix/src serviceSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/object serviceSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/data_share serviceSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/permission/src serviceSrc) -aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/cloud/src serviceSrc) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/backup/include) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/config/include) @@ -31,7 +31,7 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR}/bootstrap/include) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/directory/include) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/permission/include) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/matrix/include) -include_directories(${CMAKE_CURRENT_SOURCE_DIR}/cloud/include) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/cloud) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/rdb) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/kvdb) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../framework/include) diff --git a/datamgr_service/services/distributeddataservice/service/cloud/cloud_service.h b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service.h new file mode 100644 index 00000000..f360b317 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service.h @@ -0,0 +1,47 @@ +/* + * 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_DISTRIBUTED_DATA_SERVICES_CLOUD_CLOUD_SERVICE_H +#define OHOS_DISTRIBUTED_DATA_SERVICES_CLOUD_CLOUD_SERVICE_H +#include +#include +#include +namespace OHOS::CloudData { +class CloudService { +public: + enum TransId : int32_t { + TRANS_HEAD, + TRANS_ENABLE_CLOUD = TRANS_HEAD, + TRANS_DISABLE_CLOUD, + TRANS_CHANGE_APP_SWITCH, + TRANS_CLEAN, + TRANS_NOTIFY_DATA_CHANGE, + TRANS_BUTT, + }; + enum Action : int32_t { + CLEAR_CLOUD_INFO, + CLEAR_CLOUD_DATA_AND_INFO, + CLEAR_CLOUD_BUTT + }; + virtual ~CloudService() = 0; + virtual int32_t EnableCloud(const std::string &id, const std::map &switches) = 0; + virtual int32_t DisableCloud(const std::string &id) = 0; + virtual int32_t ChangeAppSwitch(const std::string &id, const std::string &bundleName, bool isOn) = 0; + virtual int32_t Clean(const std::string &id, const std::map &actions) = 0; + virtual int32_t NotifyDataChange(const std::string &id, const std::string &bundleName) = 0; +}; +} // namespace OHOS::CloudData + +#endif // OHOS_DISTRIBUTED_DATA_SERVICES_CLOUD_CLOUD_SERVICE_H diff --git a/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.h b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.h index a798d70e..50644cec 100644 --- a/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.h +++ b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.h @@ -13,11 +13,12 @@ * limitations under the License. */ -#ifndef OHOS_DISTRIBUTED_DATA_SERVICES_CLOUD_CLOUD_DATA_FEATURE_H -#define OHOS_DISTRIBUTED_DATA_SERVICES_CLOUD_CLOUD_DATA_FEATURE_H -namespace OHOS::DistributedData { -class CloudServiceImpl : public { +#ifndef OHOS_DISTRIBUTED_DATA_SERVICES_CLOUD_CLOUD_SERVICE_IMPL_H +#define OHOS_DISTRIBUTED_DATA_SERVICES_CLOUD_CLOUD_SERVICE_IMPL_H +#include "cloud_service_stub.h" +namespace OHOS::CloudData { +class CloudServiceImpl : public CloudServiceStub { }; } // namespace OHOS::DistributedData -#endif // OHOS_DISTRIBUTED_DATA_SERVICES_CLOUD_CLOUD_DATA_FEATURE_H +#endif // OHOS_DISTRIBUTED_DATA_SERVICES_CLOUD_CLOUD_SERVICE_IMPL_H diff --git a/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_stub.cpp b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_stub.cpp new file mode 100644 index 00000000..de682439 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_stub.cpp @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#define LOG_TAG "CloudServiceStub" +#include "cloud_service_stub.h" + +#include + +#include "ipc_skeleton.h" +#include "log_print.h" +#include "utils/anonymous.h" +namespace OHOS::CloudData { +using namespace DistributedData; +const CloudServiceStub::Handler CloudServiceStub::HANDLERS[TRANS_BUTT] = { + &CloudServiceStub::EnableCloud, + &CloudServiceStub::DisableCloud, + &CloudServiceStub::ChangeAppSwitch, + &CloudServiceStub::Clean, + &CloudServiceStub::NotifyDataChange, +}; + +int CloudServiceStub::OnRemoteRequest(uint32_t code, OHOS::MessageParcel &data, OHOS::MessageParcel &reply) +{ + ZLOGI("code:%{public}u callingPid:%{public}u", code, IPCSkeleton::GetCallingPid()); + std::u16string local = CloudServiceStub::GetDescriptor(); + std::u16string remote = data.ReadInterfaceToken(); + if (local != remote) { + ZLOGE("local is not equal to remote"); + return -1; + } + + if (TRANS_HEAD > code || code >= TRANS_BUTT || HANDLERS[code] == nullptr) { + ZLOGE("not support code:%{public}u, BUTT:%{public}d", code, TRANS_BUTT); + return -1; + } + std::string id; + if (!ITypesUtil::Unmarshal(data, id)) { + ZLOGE("Unmarshal id:%{public}s", Anonymous::Change(id).c_str()); + return IPC_STUB_INVALID_DATA_ERR; + } + return (this->*HANDLERS[code])(id, data, reply); +} + +int32_t CloudServiceStub::EnableCloud(const std::string &id, MessageParcel &data, MessageParcel &reply) +{ + return 0; +} + +int32_t CloudServiceStub::DisableCloud(const std::string &id, MessageParcel &data, MessageParcel &reply) +{ + return 0; +} + +int32_t CloudServiceStub::ChangeAppSwitch(const std::string &id, MessageParcel &data, MessageParcel &reply) +{ + return 0; +} + +int32_t CloudServiceStub::Clean(const std::string &id, MessageParcel &data, MessageParcel &reply) +{ + return 0; +} + +int32_t CloudServiceStub::NotifyDataChange(const std::string &id, MessageParcel &data, MessageParcel &reply) +{ + return 0; +} +} // namespace OHOS::CloudData diff --git a/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_stub.h b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_stub.h new file mode 100644 index 00000000..32443fe2 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_stub.h @@ -0,0 +1,37 @@ +/* + * 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_DISTRIBUTED_DATA_SERVICES_CLOUD_CLOUD_SERVICE_STUB_H +#define OHOS_DISTRIBUTED_DATA_SERVICES_CLOUD_CLOUD_SERVICE_STUB_H +#include "cloud_service.h" +#include "feature/feature_system.h" +#include "iremote_broker.h" +namespace OHOS::CloudData { +class CloudServiceStub : public CloudService, public DistributedData::FeatureSystem::Feature { +public: + DECLARE_INTERFACE_DESCRIPTOR(u"OHOS.CloudData.CloudServer"); + int OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply) override; + +private: + using Handler = int32_t (CloudServiceStub::*)(const std::string &id, MessageParcel &data, MessageParcel &reply); + int32_t EnableCloud(const std::string &id, MessageParcel &data, MessageParcel &reply); + int32_t DisableCloud(const std::string &id, MessageParcel &data, MessageParcel &reply); + int32_t ChangeAppSwitch(const std::string &id, MessageParcel &data, MessageParcel &reply); + int32_t Clean(const std::string &id, MessageParcel &data, MessageParcel &reply); + int32_t NotifyDataChange(const std::string &id, MessageParcel &data, MessageParcel &reply); + static const Handler HANDLERS[TRANS_BUTT]; +}; +} // namespace OHOS::CloudData +#endif // OHOS_DISTRIBUTED_DATA_SERVICES_CLOUD_CLOUD_SERVICE_STUB_H diff --git a/kv_store/frameworks/common/log_print.h b/kv_store/frameworks/common/log_print.h index 717da466..274031b0 100644 --- a/kv_store/frameworks/common/log_print.h +++ b/kv_store/frameworks/common/log_print.h @@ -26,7 +26,7 @@ static inline OHOS::HiviewDFX::HiLogLabel LogLabel() { return { LOG_CORE, 0xD001610, "ZDDS" }; } -} // end namespace DistributesdKv +} // namespace DistributedKv namespace DistributedData { static inline OHOS::HiviewDFX::HiLogLabel LogLabel() @@ -42,6 +42,13 @@ static inline OHOS::HiviewDFX::HiLogLabel LogLabel() } } // end namespace DistributedKVStore +namespace CloudData { +static inline OHOS::HiviewDFX::HiLogLabel LogLabel() +{ + return { LOG_CORE, 0xD001613, "CLOUD" }; +} +} // end namespace CloudData + namespace AppDistributedKv { static inline OHOS::HiviewDFX::HiLogLabel LogLabel() { @@ -66,25 +73,25 @@ static inline OHOS::HiviewDFX::HiLogLabel LogLabel() namespace DistributedObject { static inline OHOS::HiviewDFX::HiLogLabel LogLabel() { - return { LOG_CORE, 0xD001654, "DOBJECT" }; + return { LOG_CORE, 0xD001654, "DOBJECT" }; } } // end namespace DistributedObject } // end namespace OHOS #define ZLOGD(fmt, ...) \ - OHOS::HiviewDFX::HiLog::Debug(LogLabel(), LOG_TAG "::%{public}s: " fmt, __FUNCTION__, ##__VA_ARGS__) + OHOS::HiviewDFX::HiLog::Debug(LogLabel(), LOG_TAG "::%{public}s: " fmt, __FUNCTION__, ##__VA_ARGS__) #define ZLOGI(fmt, ...) \ - OHOS::HiviewDFX::HiLog::Info(LogLabel(), LOG_TAG "::%{public}s: " fmt, __FUNCTION__, ##__VA_ARGS__) + OHOS::HiviewDFX::HiLog::Info(LogLabel(), LOG_TAG "::%{public}s: " fmt, __FUNCTION__, ##__VA_ARGS__) #define ZLOGW(fmt, ...) \ - OHOS::HiviewDFX::HiLog::Warn(LogLabel(), LOG_TAG "::%{public}s: " fmt, __FUNCTION__, ##__VA_ARGS__) + OHOS::HiviewDFX::HiLog::Warn(LogLabel(), LOG_TAG "::%{public}s: " fmt, __FUNCTION__, ##__VA_ARGS__) #define ZLOGE(fmt, ...) \ - OHOS::HiviewDFX::HiLog::Error(LogLabel(), LOG_TAG "::%{public}s: " fmt, __FUNCTION__, ##__VA_ARGS__) + OHOS::HiviewDFX::HiLog::Error(LogLabel(), LOG_TAG "::%{public}s: " fmt, __FUNCTION__, ##__VA_ARGS__) #else - #error // unknown system +#error // unknown system #endif #endif // DISTRIBUTEDDATA_LOG_PRINT_H -- Gitee From 36724fe145446617072f90c6da8ee60f2f622ca9 Mon Sep 17 00:00:00 2001 From: Sven Wang Date: Wed, 29 Mar 2023 10:27:16 +0800 Subject: [PATCH 04/44] update Signed-off-by: Sven Wang --- .../service/cloud/cloud_service.h | 11 +++- .../service/cloud/cloud_service_impl.cpp | 40 +++++++++++++ .../service/cloud/cloud_service_impl.h | 16 +++++ .../service/cloud/cloud_service_stub.cpp | 59 +++++++++++++------ .../service/cloud/cloud_service_stub.h | 10 ++-- .../js}/cloud_data/BUILD.gn | 0 6 files changed, 111 insertions(+), 25 deletions(-) rename relational_store/interfaces/{inner_api => kits/js}/cloud_data/BUILD.gn (100%) diff --git a/datamgr_service/services/distributeddataservice/service/cloud/cloud_service.h b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service.h index f360b317..df2d07e5 100644 --- a/datamgr_service/services/distributeddataservice/service/cloud/cloud_service.h +++ b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service.h @@ -35,10 +35,15 @@ public: CLEAR_CLOUD_DATA_AND_INFO, CLEAR_CLOUD_BUTT }; - virtual ~CloudService() = 0; - virtual int32_t EnableCloud(const std::string &id, const std::map &switches) = 0; + + enum Switch : int32_t { + SWITCH_ON, + SWITCH_OFF + }; + virtual ~CloudService() = default; + virtual int32_t EnableCloud(const std::string &id, const std::map &switches) = 0; virtual int32_t DisableCloud(const std::string &id) = 0; - virtual int32_t ChangeAppSwitch(const std::string &id, const std::string &bundleName, bool isOn) = 0; + virtual int32_t ChangeAppSwitch(const std::string &id, const std::string &bundleName, int32_t appSwitch) = 0; virtual int32_t Clean(const std::string &id, const std::map &actions) = 0; virtual int32_t NotifyDataChange(const std::string &id, const std::string &bundleName) = 0; }; diff --git a/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.cpp b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.cpp index f3e4990d..354a79a1 100644 --- a/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.cpp +++ b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.cpp @@ -14,3 +14,43 @@ */ #include "cloud_service_impl.h" + +#include "feature/feature_system.h" +namespace OHOS::CloudData { +using namespace DistributedData; +__attribute__((used)) CloudServiceImpl::Factory CloudServiceImpl::factory_; +CloudServiceImpl::Factory::Factory() { + FeatureSystem::GetInstance().RegisterCreator("cloud", [this]() { + if (product_ == nullptr) { + product_ = std::make_shared(); + } + return product_; + }); +} +CloudServiceImpl::Factory::~Factory() {} + +int32_t CloudServiceImpl::EnableCloud(const std::string &id, const std::map &switches) +{ + return 0; +} + +int32_t CloudServiceImpl::DisableCloud(const std::string &id) +{ + return 0; +} + +int32_t CloudServiceImpl::ChangeAppSwitch(const std::string &id, const std::string &bundleName, int32_t appSwitch) +{ + return 0; +} + +int32_t CloudServiceImpl::Clean(const std::string &id, const std::map &actions) +{ + return 0; +} + +int32_t CloudServiceImpl::NotifyDataChange(const std::string &id, const std::string &bundleName) +{ + return 0; +} +} \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.h b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.h index 50644cec..203bcc45 100644 --- a/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.h +++ b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.h @@ -18,6 +18,22 @@ #include "cloud_service_stub.h" namespace OHOS::CloudData { class CloudServiceImpl : public CloudServiceStub { +public: + ~CloudServiceImpl() = default; + int32_t EnableCloud(const std::string &id, const std::map &switches) override; + int32_t DisableCloud(const std::string &id) override; + int32_t ChangeAppSwitch(const std::string &id, const std::string &bundleName, int32_t appSwitch) override; + int32_t Clean(const std::string &id, const std::map &actions) override; + int32_t NotifyDataChange(const std::string &id, const std::string &bundleName) override; +private: + class Factory { + public: + Factory(); + ~Factory(); + private: + std::shared_ptr product_; + }; + static Factory factory_; }; } // namespace OHOS::DistributedData diff --git a/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_stub.cpp b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_stub.cpp index de682439..2ccf869e 100644 --- a/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_stub.cpp +++ b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_stub.cpp @@ -15,19 +15,18 @@ #define LOG_TAG "CloudServiceStub" #include "cloud_service_stub.h" -#include - #include "ipc_skeleton.h" +#include "itypes_util.h" #include "log_print.h" #include "utils/anonymous.h" namespace OHOS::CloudData { using namespace DistributedData; const CloudServiceStub::Handler CloudServiceStub::HANDLERS[TRANS_BUTT] = { - &CloudServiceStub::EnableCloud, - &CloudServiceStub::DisableCloud, - &CloudServiceStub::ChangeAppSwitch, - &CloudServiceStub::Clean, - &CloudServiceStub::NotifyDataChange, + &CloudServiceStub::OnEnableCloud, + &CloudServiceStub::OnDisableCloud, + &CloudServiceStub::OnChangeAppSwitch, + &CloudServiceStub::OnClean, + &CloudServiceStub::OnNotifyDataChange, }; int CloudServiceStub::OnRemoteRequest(uint32_t code, OHOS::MessageParcel &data, OHOS::MessageParcel &reply) @@ -52,28 +51,54 @@ int CloudServiceStub::OnRemoteRequest(uint32_t code, OHOS::MessageParcel &data, return (this->*HANDLERS[code])(id, data, reply); } -int32_t CloudServiceStub::EnableCloud(const std::string &id, MessageParcel &data, MessageParcel &reply) +int32_t CloudServiceStub::OnEnableCloud(const std::string &id, MessageParcel &data, MessageParcel &reply) { - return 0; + std::map switches; + if (!ITypesUtil::Unmarshal(data, switches)) { + ZLOGE("Unmarshal id:%{public}s", Anonymous::Change(id).c_str()); + return IPC_STUB_INVALID_DATA_ERR; + } + auto result = EnableCloud(id, switches); + return ITypesUtil::Marshal(reply, result) ? ERR_NONE : IPC_STUB_WRITE_PARCEL_ERR; } -int32_t CloudServiceStub::DisableCloud(const std::string &id, MessageParcel &data, MessageParcel &reply) +int32_t CloudServiceStub::OnDisableCloud(const std::string &id, MessageParcel &data, MessageParcel &reply) { - return 0; + auto result = DisableCloud(id); + return ITypesUtil::Marshal(reply, result) ? ERR_NONE : IPC_STUB_WRITE_PARCEL_ERR; } -int32_t CloudServiceStub::ChangeAppSwitch(const std::string &id, MessageParcel &data, MessageParcel &reply) +int32_t CloudServiceStub::OnChangeAppSwitch(const std::string &id, MessageParcel &data, MessageParcel &reply) { - return 0; + std::string bundleName; + int32_t appSwitch = SWITCH_OFF; + if (!ITypesUtil::Unmarshal(data, bundleName, appSwitch)) { + ZLOGE("Unmarshal id:%{public}s", Anonymous::Change(id).c_str()); + return IPC_STUB_INVALID_DATA_ERR; + } + auto result = ChangeAppSwitch(id, bundleName, appSwitch); + return ITypesUtil::Marshal(reply, result) ? ERR_NONE : IPC_STUB_WRITE_PARCEL_ERR; } -int32_t CloudServiceStub::Clean(const std::string &id, MessageParcel &data, MessageParcel &reply) +int32_t CloudServiceStub::OnClean(const std::string &id, MessageParcel &data, MessageParcel &reply) { - return 0; + std::map actions; + if (!ITypesUtil::Unmarshal(data, actions)) { + ZLOGE("Unmarshal id:%{public}s", Anonymous::Change(id).c_str()); + return IPC_STUB_INVALID_DATA_ERR; + } + auto result = Clean(id, actions); + return ITypesUtil::Marshal(reply, result) ? ERR_NONE : IPC_STUB_WRITE_PARCEL_ERR; } -int32_t CloudServiceStub::NotifyDataChange(const std::string &id, MessageParcel &data, MessageParcel &reply) +int32_t CloudServiceStub::OnNotifyDataChange(const std::string &id, MessageParcel &data, MessageParcel &reply) { - return 0; + std::string bundleName; + if (!ITypesUtil::Unmarshal(data, bundleName)) { + ZLOGE("Unmarshal id:%{public}s", Anonymous::Change(id).c_str()); + return IPC_STUB_INVALID_DATA_ERR; + } + auto result = NotifyDataChange(id, bundleName); + return ITypesUtil::Marshal(reply, result) ? ERR_NONE : IPC_STUB_WRITE_PARCEL_ERR; } } // namespace OHOS::CloudData diff --git a/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_stub.h b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_stub.h index 32443fe2..4175015d 100644 --- a/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_stub.h +++ b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_stub.h @@ -26,11 +26,11 @@ public: private: using Handler = int32_t (CloudServiceStub::*)(const std::string &id, MessageParcel &data, MessageParcel &reply); - int32_t EnableCloud(const std::string &id, MessageParcel &data, MessageParcel &reply); - int32_t DisableCloud(const std::string &id, MessageParcel &data, MessageParcel &reply); - int32_t ChangeAppSwitch(const std::string &id, MessageParcel &data, MessageParcel &reply); - int32_t Clean(const std::string &id, MessageParcel &data, MessageParcel &reply); - int32_t NotifyDataChange(const std::string &id, MessageParcel &data, MessageParcel &reply); + int32_t OnEnableCloud(const std::string &id, MessageParcel &data, MessageParcel &reply); + int32_t OnDisableCloud(const std::string &id, MessageParcel &data, MessageParcel &reply); + int32_t OnChangeAppSwitch(const std::string &id, MessageParcel &data, MessageParcel &reply); + int32_t OnClean(const std::string &id, MessageParcel &data, MessageParcel &reply); + int32_t OnNotifyDataChange(const std::string &id, MessageParcel &data, MessageParcel &reply); static const Handler HANDLERS[TRANS_BUTT]; }; } // namespace OHOS::CloudData diff --git a/relational_store/interfaces/inner_api/cloud_data/BUILD.gn b/relational_store/interfaces/kits/js/cloud_data/BUILD.gn similarity index 100% rename from relational_store/interfaces/inner_api/cloud_data/BUILD.gn rename to relational_store/interfaces/kits/js/cloud_data/BUILD.gn -- Gitee From d1cfe65c8ab32fce698e480bd43f46e83c70d17c Mon Sep 17 00:00:00 2001 From: Sven Wang Date: Fri, 31 Mar 2023 17:06:44 +0800 Subject: [PATCH 05/44] update Signed-off-by: Sven Wang --- .../framework/cloud/asset_loader.cpp | 2 +- .../framework/cloud/auto_cache.cpp | 17 +++ .../include/serializable/serializable.h | 2 + .../framework/include/store/auto_cache.h | 44 +++++++ .../framework/include/store/general_store.h | 11 +- .../framework/include/store/general_watcher.h | 51 ++++++++ .../framework/serializable/serializable.cpp | 15 +++ .../framework/store/auto_cache.cpp | 16 +++ .../framework/store/general_watcher.cpp | 16 +++ .../service/CMakeLists.txt | 1 + .../service/cloud/cloud_service_impl.cpp | 2 +- kv_store/frameworks/common/executor_pool.h | 112 +++++++++++++++++ kv_store/frameworks/common/pool.h | 114 ++++++++++++++++++ .../js/napi}/cloud_data/BUILD.gn | 0 .../cloud_data/include}/cloud_service.h | 18 +-- 15 files changed, 408 insertions(+), 13 deletions(-) create mode 100644 datamgr_service/services/distributeddataservice/framework/cloud/auto_cache.cpp create mode 100644 datamgr_service/services/distributeddataservice/framework/include/store/auto_cache.h create mode 100644 datamgr_service/services/distributeddataservice/framework/include/store/general_watcher.h create mode 100644 datamgr_service/services/distributeddataservice/framework/store/auto_cache.cpp create mode 100644 datamgr_service/services/distributeddataservice/framework/store/general_watcher.cpp create mode 100644 kv_store/frameworks/common/executor_pool.h create mode 100644 kv_store/frameworks/common/pool.h rename relational_store/{interfaces/kits/js => frameworks/js/napi}/cloud_data/BUILD.gn (100%) rename {datamgr_service/services/distributeddataservice/service/cloud => relational_store/interfaces/inner_api/cloud_data/include}/cloud_service.h (83%) diff --git a/datamgr_service/services/distributeddataservice/framework/cloud/asset_loader.cpp b/datamgr_service/services/distributeddataservice/framework/cloud/asset_loader.cpp index a1f54cc1..adbf4f08 100644 --- a/datamgr_service/services/distributeddataservice/framework/cloud/asset_loader.cpp +++ b/datamgr_service/services/distributeddataservice/framework/cloud/asset_loader.cpp @@ -13,4 +13,4 @@ * limitations under the License. */ -#include "asset_loader.h" +#include "cloud/asset_loader.h" diff --git a/datamgr_service/services/distributeddataservice/framework/cloud/auto_cache.cpp b/datamgr_service/services/distributeddataservice/framework/cloud/auto_cache.cpp new file mode 100644 index 00000000..c080d640 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/framework/cloud/auto_cache.cpp @@ -0,0 +1,17 @@ +/* + * 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. + */ + +#include "store_auto_cache.h" + diff --git a/datamgr_service/services/distributeddataservice/framework/include/serializable/serializable.h b/datamgr_service/services/distributeddataservice/framework/include/serializable/serializable.h index dc2337c9..4b16f8dd 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/serializable/serializable.h +++ b/datamgr_service/services/distributeddataservice/framework/include/serializable/serializable.h @@ -55,6 +55,7 @@ public: API_EXPORT static bool GetValue(const json &node, const std::string &name, uint32_t &value); API_EXPORT static bool GetValue(const json &node, const std::string &name, int32_t &value); API_EXPORT static bool GetValue(const json &node, const std::string &name, int64_t &value); + API_EXPORT static bool GetValue(const json &node, const std::string &name, uint64_t &value); API_EXPORT static bool GetValue(const json &node, const std::string &name, bool &value); API_EXPORT static bool GetValue(const json &node, const std::string &name, std::vector &value); API_EXPORT static bool GetValue(const json &node, const std::string &name, Serializable &value); @@ -62,6 +63,7 @@ public: API_EXPORT static bool SetValue(json &node, const uint32_t &value); API_EXPORT static bool SetValue(json &node, const int32_t &value); API_EXPORT static bool SetValue(json &node, const int64_t &value); + API_EXPORT static bool SetValue(json &node, const uint64_t &value); API_EXPORT static bool SetValue(json &node, const bool &value); API_EXPORT static bool SetValue(json &node, const std::vector &value); API_EXPORT static bool SetValue(json &node, const Serializable &value); diff --git a/datamgr_service/services/distributeddataservice/framework/include/store/auto_cache.h b/datamgr_service/services/distributeddataservice/framework/include/store/auto_cache.h new file mode 100644 index 00000000..e1d4ee55 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/framework/include/store/auto_cache.h @@ -0,0 +1,44 @@ +/* + * 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_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_STORE_STORE_AUTO_CACHE_H +#define OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_STORE_STORE_AUTO_CACHE_H +#include + +#include "concurrent_map.h" +#include "metadata/store_meta_data.h" +#include "store/general_store.h" +#include "store/general_watcher.h" +#include "task_scheduler.h" +namespace OHOS::DistributedData { +class AutoCache { +public: + using Store = std::shared_ptr; + using Time = std::chrono::steady_clock::time_point; + using Executor = TaskScheduler; + AutoCache(std::shared_ptr executor); + Store Get(const StoreMetaData &data, std::shared_ptr watchers, int32_t &status); + +private: + void GarbageCollect(); + + static constexpr int64_t INTERVAL = 1; + static constexpr size_t TIME_TASK_NUM = 1; + ConcurrentMap> stores_; + std::shared_ptr executor_; +}; +} // namespace OHOS::DistributedData + +#endif // OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_STORE_STORE_AUTO_CACHE_H diff --git a/datamgr_service/services/distributeddataservice/framework/include/store/general_store.h b/datamgr_service/services/distributeddataservice/framework/include/store/general_store.h index f7f56229..86d84236 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/store/general_store.h +++ b/datamgr_service/services/distributeddataservice/framework/include/store/general_store.h @@ -13,12 +13,13 @@ * limitations under the License. */ -#ifndef OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_STORE_INNER_DB_STORE_H -#define OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_STORE_INNER_DB_STORE_H +#ifndef OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_STORE_GENERAL_STORE_H +#define OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_STORE_GENERAL_STORE_H #include #include "store/asset.h" #include "store/cursor.h" +#include "store/general_watcher.h" namespace OHOS::DistributedData { class GeneralStore { public: @@ -27,12 +28,14 @@ public: using Value = std::variant; using Values = std::vector; using VBucket = std::map; - virtual ~GeneralStore() = 0; + virtual ~GeneralStore() = default; virtual int32_t Close() = 0; virtual int32_t Insert(const std::string &table, VBucket &&values) = 0; virtual int32_t Update(const std::string &table, const std::string &sql, VBucket &&values) = 0; virtual int32_t Delete(const std::string &table, const std::string &sql, Values &&args) = 0; virtual std::shared_ptr Query(const std::string &table, const std::string &sql, Values &&args) = 0; + virtual int32_t Watch(int32_t origin, std::shared_ptr watcher) = 0; + virtual int32_t Unwatch(int32_t origin, std::shared_ptr watcher) = 0; }; } // namespace OHOS::DistributedData -#endif // OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_STORE_INNER_DB_STORE_H +#endif // OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_STORE_GENERAL_STORE_H diff --git a/datamgr_service/services/distributeddataservice/framework/include/store/general_watcher.h b/datamgr_service/services/distributeddataservice/framework/include/store/general_watcher.h new file mode 100644 index 00000000..cc67afe6 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/framework/include/store/general_watcher.h @@ -0,0 +1,51 @@ +/* + * 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_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_STORE_GENERAL_WATCHER_H +#define OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_STORE_GENERAL_WATCHER_H +#include +#include +#include +#include +#include + +#include "store/asset.h" +#include "visibility.h" +namespace OHOS::DistributedData { +class GeneralWatcher { +public: + enum Origin : int32_t { + ORIGIN_CLOUD, + ORIGIN_LOCAL, + ORIGIN_REMOTE, + ORIGIN_BUTT, + }; + enum ChangeOp : int32_t { + OP_INSERT, + OP_UPDATE, + OP_DELETE, + OP_BUTT, + }; + using Assets = std::vector; + using Bytes = std::vector; + using Value = std::variant; + using Values = std::vector; + using VBucket = std::map; + API_EXPORT virtual ~GeneralWatcher() = default; + virtual int32_t OnChange(Origin origin, const std::string &id) = 0; + virtual int32_t OnChange(Origin origin, const std::string &id, std::vector &&values) = 0; +}; +} +#endif // OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_STORE_GENERAL_WATCHER_H diff --git a/datamgr_service/services/distributeddataservice/framework/serializable/serializable.cpp b/datamgr_service/services/distributeddataservice/framework/serializable/serializable.cpp index 9622af95..c9b62933 100644 --- a/datamgr_service/services/distributeddataservice/framework/serializable/serializable.cpp +++ b/datamgr_service/services/distributeddataservice/framework/serializable/serializable.cpp @@ -103,6 +103,16 @@ bool Serializable::GetValue(const json &node, const std::string &name, int64_t & return true; } +bool Serializable::GetValue(const json &node, const std::string &name, uint64_t &value) +{ + auto &subNode = GetSubNode(node, name); + if (subNode.is_null() || !subNode.is_number_unsigned()) { + return false; + } + subNode.get_to(value); + return true; +} + bool Serializable::GetValue(const json &node, const std::string &name, bool &value) { auto &subNode = GetSubNode(node, name); @@ -156,6 +166,11 @@ bool Serializable::SetValue(json &node, const int64_t &value) return true; } +bool Serializable::SetValue(json &node, const uint64_t &value) +{ + node = value; + return true; +} bool Serializable::SetValue(json &node, const bool &value) { node = value; diff --git a/datamgr_service/services/distributeddataservice/framework/store/auto_cache.cpp b/datamgr_service/services/distributeddataservice/framework/store/auto_cache.cpp new file mode 100644 index 00000000..c7ed4de0 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/framework/store/auto_cache.cpp @@ -0,0 +1,16 @@ +/* + * 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. + */ + +#include "store/auto_cache.h" diff --git a/datamgr_service/services/distributeddataservice/framework/store/general_watcher.cpp b/datamgr_service/services/distributeddataservice/framework/store/general_watcher.cpp new file mode 100644 index 00000000..336d4ce8 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/framework/store/general_watcher.cpp @@ -0,0 +1,16 @@ +/* + * 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. + */ + +#include "store/general_watcher.h" diff --git a/datamgr_service/services/distributeddataservice/service/CMakeLists.txt b/datamgr_service/services/distributeddataservice/service/CMakeLists.txt index 8e04aa87..6c0f84ad 100644 --- a/datamgr_service/services/distributeddataservice/service/CMakeLists.txt +++ b/datamgr_service/services/distributeddataservice/service/CMakeLists.txt @@ -47,6 +47,7 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../adapter/include/permission) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../adapter/include/security) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../adapter/include/utils) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../app/src) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../../../relational_store/interfaces/inner_api/cloud_data/include) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../../../relational_store/interfaces/inner_api/rdb/include) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../../../relational_store/interfaces/inner_api/rdb_data_share_adapter/include) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../../../data_share/interfaces/inner_api/common/include) diff --git a/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.cpp b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.cpp index 354a79a1..b78e07b7 100644 --- a/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.cpp +++ b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.cpp @@ -20,7 +20,7 @@ namespace OHOS::CloudData { using namespace DistributedData; __attribute__((used)) CloudServiceImpl::Factory CloudServiceImpl::factory_; CloudServiceImpl::Factory::Factory() { - FeatureSystem::GetInstance().RegisterCreator("cloud", [this]() { + FeatureSystem::GetInstance().RegisterCreator(CloudServiceImpl::SERVICE_NAME, [this]() { if (product_ == nullptr) { product_ = std::make_shared(); } diff --git a/kv_store/frameworks/common/executor_pool.h b/kv_store/frameworks/common/executor_pool.h new file mode 100644 index 00000000..28fbc95c --- /dev/null +++ b/kv_store/frameworks/common/executor_pool.h @@ -0,0 +1,112 @@ +/* + * 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_DISTRIBUTED_DATA_KV_STORE_FRAMEWORKS_COMMON_EXECUTOR_POOL_H +#define OHOS_DISTRIBUTED_DATA_KV_STORE_FRAMEWORKS_COMMON_EXECUTOR_POOL_H +#include "pool.h" +namespace OHOS { +class ExecutorPool { +public: + ~ExecutorPool() { + pool_.Clean([](Executor *executor) { + executor->Stop(true); + }) + } + void Execute() { + InnerTask innerTask; + auto executor = pool_.Get(); + if (executor == nullptr) { + execs_.push_back(innerTask); + return taskId; + } + executor.Bind(&execs_, [this](Executor *exe)->bool { + return pool_.Release(exe); + }); + executor.SetTask(innerTask); + } + void Schedule(Task task) + { + InnerTask innerTask; + if (scheduler_ == nullptr) { + scheduler_ = pool_.Get(true); + scheduler_.Bind(&delayTask_); + scheduler_.SetTask(startTask); + } + auto run = [&innerTask, task, this] { + ExecuteInner(task, innerTask.taskId); + if (innerTask.interval != 0) { + innerTask.time = std::chrono::steady_clock::now() + std::second(innerTask.interval); + delayTask_.push(innerTask); + } + }; + innerTask.exec = std::move(run); + delayTask_.push(innerTask); + scheduler_.SetTask(startTask); + } +private: + struct InnerTask { + std::function exec; + + }; + class Executor { + public: + void SetTask(InnerTask &innerTask) + { + std::gaud_lock lock; + currentTask_ = innerTask; + notify; + } + void Bind(std::queue *queue, std::function idle, std::function release); + { + queue_ = queue; + idle_ = idle; + release_ = relase; + }; + void Stop(bool wait = false) { + running_ = false; + notify; + stop_wait(); + }; + private: + void Run() + { + do { + do { + InnerTask task = currentTask_; + while (running_ && task.Valid()) { + task(); + task = waits_.Pop(); + } + waits_ = nullptr; + std::gaud_lock lock; + idle_(this); + } while (running_ && wait_time(lock)); + } while (release_(this)); + stop_notify(); + } + bool running_ = true; + std::queue *waits_; + InnerTask currentTask_; + std::thread thread_; + std::function release_; + }; + Pool pool_; + std::shared_ptr scheduler_; + std::queue execs_; + std::queue delayTask_; +}; +} + +#endif // OHOS_DISTRIBUTED_DATA_KV_STORE_FRAMEWORKS_COMMON_EXECUTOR_POOL_H diff --git a/kv_store/frameworks/common/pool.h b/kv_store/frameworks/common/pool.h new file mode 100644 index 00000000..0c5e6676 --- /dev/null +++ b/kv_store/frameworks/common/pool.h @@ -0,0 +1,114 @@ +/* + * 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_DISTRIBUTED_DATA_KV_STORE_FRAMEWORKS_COMMON_POOL_H +#define OHOS_DISTRIBUTED_DATA_KV_STORE_FRAMEWORKS_COMMON_POOL_H +namespace OHOS { +template +class Pool { +public: + Pool(uint32_t capability) : capability_(capability) {} + T *Get(bool isForce = false) + { + std::lock_gurd<> + if (idle_ == nullptr) { + if (!isForce && current_ >= capability_) { + return nullptr; + } + auto cur = new Node(); + cur->next = nullptr; + cur->prev = nullptr; + idle_ = cur; + current_++; + } + Node *cur = idle_; + idle_ = idle_->next; + if (idle_ != nullptr) { + idle_->prev = nullptr; + } + + cur->next = busy_; + if (busy_ != nullptr) { + cur->prev = busy_->prev; + busy_->prev = cur; + } + busy_ = cur; + return cur->data; + }; + + int32_t Release(T *data) + { + std::lock_gurd<> + Node *cur = idle_ + while (cur != nullptr) { + if (cur->data == data) { + cur->next->prev = cur->prev; + cur->prev->next = cur->next; + if (idle_ == cur) { + idle_ = cur->next; + } + delete cur; + return true; + } + } + return false; + } + + int32_t Idle(T *data) + { + std::lock_gurd<> + Node *cur = static_cast(data); + cur->next->prev = cur->prev; + cur->prev->next = cur->next; + cur->prev = nullptr; + cur->next = idle_; + idle_->prev = cur; + idle_ = cur; + } + + int32_t Clean(std::function<> close) + { + while(busy_ != nullptr) { + // unlock + close(busy_); + // luck + } + while(idle_ != nullptr) { + // unlock + close(busy_); + // luck + } + } + + +private: + struct Node { + Node *prev = nullptr; + Node *next = nullptr; + T *data = new T(); + ~Node() { + delete data; + } + }; + + uint32_t capability_; + uint32_t current_ = 0; + Node *idle_ = nullptr; + Node *busy_ = nullptr; + std::mutex mutex_; +}; +} // namespace OHOS + +#endif // OHOS_DISTRIBUTED_DATA_KV_STORE_FRAMEWORKS_COMMON_POOL_H diff --git a/relational_store/interfaces/kits/js/cloud_data/BUILD.gn b/relational_store/frameworks/js/napi/cloud_data/BUILD.gn similarity index 100% rename from relational_store/interfaces/kits/js/cloud_data/BUILD.gn rename to relational_store/frameworks/js/napi/cloud_data/BUILD.gn diff --git a/datamgr_service/services/distributeddataservice/service/cloud/cloud_service.h b/relational_store/interfaces/inner_api/cloud_data/include/cloud_service.h similarity index 83% rename from datamgr_service/services/distributeddataservice/service/cloud/cloud_service.h rename to relational_store/interfaces/inner_api/cloud_data/include/cloud_service.h index df2d07e5..260c1a06 100644 --- a/datamgr_service/services/distributeddataservice/service/cloud/cloud_service.h +++ b/relational_store/interfaces/inner_api/cloud_data/include/cloud_service.h @@ -13,15 +13,16 @@ * limitations under the License. */ -#ifndef OHOS_DISTRIBUTED_DATA_SERVICES_CLOUD_CLOUD_SERVICE_H -#define OHOS_DISTRIBUTED_DATA_SERVICES_CLOUD_CLOUD_SERVICE_H +#ifndef OHOS_DISTRIBUTED_DATA_CLOUD_CLOUD_SERVICE_H +#define OHOS_DISTRIBUTED_DATA_CLOUD_CLOUD_SERVICE_H #include #include #include namespace OHOS::CloudData { class CloudService { public: - enum TransId : int32_t { + enum TransId : int32_t + { TRANS_HEAD, TRANS_ENABLE_CLOUD = TRANS_HEAD, TRANS_DISABLE_CLOUD, @@ -30,16 +31,20 @@ public: TRANS_NOTIFY_DATA_CHANGE, TRANS_BUTT, }; - enum Action : int32_t { + enum Action : int32_t + { CLEAR_CLOUD_INFO, CLEAR_CLOUD_DATA_AND_INFO, CLEAR_CLOUD_BUTT }; - enum Switch : int32_t { + enum Switch : int32_t + { SWITCH_ON, SWITCH_OFF }; + + static constexpr const char *SERVICE_NAME = "cloud"; virtual ~CloudService() = default; virtual int32_t EnableCloud(const std::string &id, const std::map &switches) = 0; virtual int32_t DisableCloud(const std::string &id) = 0; @@ -48,5 +53,4 @@ public: virtual int32_t NotifyDataChange(const std::string &id, const std::string &bundleName) = 0; }; } // namespace OHOS::CloudData - -#endif // OHOS_DISTRIBUTED_DATA_SERVICES_CLOUD_CLOUD_SERVICE_H +#endif // OHOS_DISTRIBUTED_DATA_CLOUD_CLOUD_SERVICE_H -- Gitee From dcd6893c85f47268dea61c464891bfae0dabe1bc Mon Sep 17 00:00:00 2001 From: Sven Wang Date: Tue, 4 Apr 2023 15:51:12 +0800 Subject: [PATCH 06/44] update Signed-off-by: Sven Wang --- .../devicemanagersdk/include/device_manager.h | 2 + .../include/device_manager_impl.h | 4 + mock/src/mock_device_manager.cpp | 7 + relational_store/CMakeLists.txt | 2 + .../js/napi/common/src/js_utils.cpp | 12 +- .../src/napi_data_ability_predicates.cpp | 6 +- .../js/napi/rdb/include/napi_rdb_error.h | 3 +- .../js/napi/rdb/include/napi_rdb_store.h | 3 - .../js/napi/rdb/mock/include/napi_rdb_store.h | 2 - .../js/napi/rdb/src/napi_rdb_predicates.cpp | 6 +- .../js/napi/rdb/src/napi_rdb_store.cpp | 120 +-- .../js/napi/rdb/src/napi_result_set.cpp | 6 +- .../js/napi/rdb/src/napi_values_bucket.cpp | 9 +- .../relationalstore/include/napi_rdb_error.h | 1 + .../relationalstore/include/napi_rdb_store.h | 4 +- .../src/napi_rdb_predicates.cpp | 6 +- .../relationalstore/src/napi_rdb_store.cpp | 69 +- .../relationalstore/src/napi_result_set.cpp | 6 +- .../native/appdatafwk/src/shared_block.cpp | 1 - .../native/rdb/include/rdb_manager.h | 2 +- .../native/rdb/include/rdb_manager_impl.h | 4 +- .../native/rdb/include/rdb_security_manager.h | 25 +- .../native/rdb/include/rdb_store_impl.h | 15 +- .../native/rdb/include/rdb_types_util.h | 6 + .../native/rdb/include/sqlite_config.h | 7 +- .../native/rdb/include/sqlite_connection.h | 5 +- .../rdb/include/sqlite_connection_pool.h | 2 +- .../rdb/include/sqlite_shared_result_set.h | 1 - .../native/rdb/include/sqlite_utils.h | 1 + .../native/rdb/include/step_result_set.h | 1 - .../native/rdb/mock/include/rdb_store_impl.h | 3 - .../rdb/mock/include/sqlite_connection.h | 2 +- .../rdb/mock/include/sqlite_connection_pool.h | 2 +- .../native/rdb/mock/include/sqlite_utils.h | 1 + .../native/rdb/mock/include/step_result_set.h | 1 - .../native/rdb/src/abs_predicates.cpp | 8 +- .../native/rdb/src/abs_result_set.cpp | 26 +- .../frameworks/native/rdb/src/asset_value.cpp | 3 +- .../frameworks/native/rdb/src/rdb_manager.cpp | 4 +- .../native/rdb/src/rdb_manager_impl.cpp | 45 +- .../native/rdb/src/rdb_security_manager.cpp | 972 +++++++++--------- .../native/rdb/src/rdb_store_config.cpp | 21 +- .../native/rdb/src/rdb_store_impl.cpp | 224 ++-- .../native/rdb/src/rdb_types_util.cpp | 14 +- .../frameworks/native/rdb/src/share_block.cpp | 1 - .../native/rdb/src/sqlite_config.cpp | 25 +- .../native/rdb/src/sqlite_connection.cpp | 125 ++- .../native/rdb/src/sqlite_connection_pool.cpp | 47 +- .../native/rdb/src/sqlite_database_utils.cpp | 24 +- .../rdb/src/sqlite_shared_result_set.cpp | 15 +- .../native/rdb/src/sqlite_sql_builder.cpp | 16 +- .../native/rdb/src/sqlite_statement.cpp | 26 +- .../native/rdb/src/sqlite_utils.cpp | 19 + .../native/rdb/src/step_result_set.cpp | 62 +- .../native/rdb/src/store_session.cpp | 447 -------- .../native/rdb/src/value_object.cpp | 68 +- .../native/rdb/src/values_bucket.cpp | 41 +- .../src/rdb_data_ability_utils.cpp | 8 +- .../rdb_data_share_adapter/src/rdb_utils.cpp | 7 +- .../include/rdb_device_manager_adapter.h | 47 + .../src/rdb_device_manager_adapter.cpp | 64 ++ .../interfaces/inner_api/rdb/BUILD.gn | 9 +- .../rdb/include/abs_rdb_predicates.h | 2 +- .../inner_api/rdb/include/asset_value.h | 28 + .../inner_api/rdb/include/rdb_errno.h | 10 + .../inner_api/rdb/include/rdb_store.h | 16 +- .../inner_api/rdb/include/rdb_store_config.h | 12 + .../inner_api/rdb/include/result_set.h | 6 +- .../inner_api/rdb/include/value_object.h | 129 ++- .../inner_api/rdb/include/values_bucket.h | 16 +- .../rdb/mock/include/rdb_store_config.h | 2 +- .../src/DataAbilityPredicatesJsunit.test.js | 19 - ...reBackupRestoreWithFAContextJsunit.test.js | 245 ----- .../src/RdbstorePredicatesJsunit.test.js | 17 - .../src/RdbStoreOthersCallbackPerf.js | 44 - .../src/RdbStoreDistributedJsunit.test.js | 13 +- .../src/RdbstorePredicatesJsunit.test.js | 17 - relational_store/test/native/rdb/BUILD.gn | 1 + .../rdb_store_impl_test/distributed_test.cpp | 8 +- .../rdb/unittest/rdb_encrypt_decrypt_test.cpp | 39 +- .../rdb/unittest/rdb_predicates_test.cpp | 18 + .../rdb/unittest/rdb_store_config_test.cpp | 5 +- .../rdb/unittest/rdb_store_rekey_test.cpp | 289 ++++++ .../rdb/unittest/rdb_value_bucket_test.cpp | 85 +- 84 files changed, 1915 insertions(+), 1821 deletions(-) rename datamgr_service/services/distributeddataservice/framework/cloud/auto_cache.cpp => relational_store/frameworks/native/rdb/src/asset_value.cpp (95%) delete mode 100644 relational_store/frameworks/native/rdb/src/store_session.cpp create mode 100644 relational_store/frameworks/native/rdb_device_manager_adapter/include/rdb_device_manager_adapter.h create mode 100644 relational_store/frameworks/native/rdb_device_manager_adapter/src/rdb_device_manager_adapter.cpp create mode 100644 relational_store/interfaces/inner_api/rdb/include/asset_value.h delete mode 100644 relational_store/test/js/rdb/unittest/src/RdbstoreBackupRestoreWithFAContextJsunit.test.js create mode 100644 relational_store/test/native/rdb/unittest/rdb_store_rekey_test.cpp diff --git a/mock/innerkits/device_manager/devicemanagersdk/include/device_manager.h b/mock/innerkits/device_manager/devicemanagersdk/include/device_manager.h index d926cb79..6128e720 100644 --- a/mock/innerkits/device_manager/devicemanagersdk/include/device_manager.h +++ b/mock/innerkits/device_manager/devicemanagersdk/include/device_manager.h @@ -207,6 +207,8 @@ public: * @param event event info */ virtual int32_t NotifyEvent(const std::string &pkgName, const int32_t eventId, const std::string &event) = 0; + + virtual int GetEncryptedUuidByNetworkId(const std::string &pkgName, const std::string &networkId, std::string &uuid) = 0; }; } // namespace DistributedHardware } // namespace OHOS diff --git a/mock/innerkits/device_manager/devicemanagersdk/include/device_manager_impl.h b/mock/innerkits/device_manager/devicemanagersdk/include/device_manager_impl.h index fd78f385..fa122c34 100644 --- a/mock/innerkits/device_manager/devicemanagersdk/include/device_manager_impl.h +++ b/mock/innerkits/device_manager/devicemanagersdk/include/device_manager_impl.h @@ -202,6 +202,10 @@ public: * @tc.type: FUNC */ virtual int32_t NotifyEvent(const std::string &pkgName, const int32_t eventId, const std::string &event) override; + + int GetEncryptedUuidByNetworkId(const std::string &pkgName, const std::string &networkId, + std::string &uuid) override; + private: DeviceManagerImpl() = default; ~DeviceManagerImpl() = default; diff --git a/mock/src/mock_device_manager.cpp b/mock/src/mock_device_manager.cpp index 8fa4058d..f0762595 100644 --- a/mock/src/mock_device_manager.cpp +++ b/mock/src/mock_device_manager.cpp @@ -22,6 +22,13 @@ DeviceManager &DeviceManager::GetInstance() return DeviceManagerImpl::GetInstance(); } +int DeviceManagerImpl::GetEncryptedUuidByNetworkId(const std::string &pkgName, const std::string &networkId, + std::string &uuid) +{ + uuid = networkId; + return 0; +} + DeviceManagerImpl &DeviceManagerImpl::GetInstance() { static DeviceManagerImpl instance; diff --git a/relational_store/CMakeLists.txt b/relational_store/CMakeLists.txt index 559ae0fd..cbece15b 100644 --- a/relational_store/CMakeLists.txt +++ b/relational_store/CMakeLists.txt @@ -16,6 +16,7 @@ aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/frameworks/native/dataability/s aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/frameworks/native/rdb/src relational_store_src) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/frameworks/native/rdb_data_ability_adapter/src relational_store_src) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/frameworks/native/rdb_data_share_adapter/src relational_store_src) +aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/frameworks/native/rdb_device_manager_adapter/src relational_store_src) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/frameworks/js/napi/common/src relational_store_src) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/frameworks/js/napi/dataability/src relational_store_src) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/frameworks/js/napi/rdb/src relational_store_src) @@ -29,6 +30,7 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR}/interfaces/inner_api/rdb/include include_directories(${CMAKE_CURRENT_SOURCE_DIR}/interfaces/inner_api/rdb_data_ability_adapter/include) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/interfaces/inner_api/rdb_data_share_adapter/include) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/frameworks/native/rdb_data_share_adapter/include) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/frameworks/native/rdb_device_manager_adapter/include) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../datamgr_service/services/distributeddataservice/adapter/include/dfx) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../data_share/interfaces/inner_api/common/include) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../data_share/interfaces/inner_api/consumer/include) diff --git a/relational_store/frameworks/js/napi/common/src/js_utils.cpp b/relational_store/frameworks/js/napi/common/src/js_utils.cpp index baf7b225..b87b3dee 100644 --- a/relational_store/frameworks/js/napi/common/src/js_utils.cpp +++ b/relational_store/frameworks/js/napi/common/src/js_utils.cpp @@ -26,7 +26,11 @@ std::string JSUtils::Convert2String(napi_env env, napi_value jsStr, bool useDefa str_buffer_size = (useDefaultBufSize && (str_buffer_size > DEFAULT_BUF_SIZE)) ? (DEFAULT_BUF_SIZE + BUF_CACHE_MARGIN) : (str_buffer_size + BUF_CACHE_MARGIN); - char *buf = new char[str_buffer_size]; + char *buf = new (std::nothrow) char[str_buffer_size]; + if (buf == nullptr) { + LOG_ERROR("JSUtils::Convert2String new failed, buf is nullptr"); + return ""; + } size_t len = 0; napi_get_value_string_utf8(env, jsStr, buf, str_buffer_size, &len); buf[len] = 0; @@ -37,7 +41,11 @@ std::string JSUtils::Convert2String(napi_env env, napi_value jsStr, bool useDefa int32_t JSUtils::Convert2String(napi_env env, napi_value jsStr, std::string &output) { - char *str = new char[MAX_VALUE_LENGTH + 1]; + char *str = new (std::nothrow) char[MAX_VALUE_LENGTH + 1]; + if (str == nullptr) { + LOG_ERROR("JSUtils::Convert2String new failed, str is nullptr"); + return ERR; + } size_t valueSize = 0; napi_status status = napi_get_value_string_utf8(env, jsStr, str, MAX_VALUE_LENGTH, &valueSize); if (status != napi_ok) { diff --git a/relational_store/frameworks/js/napi/dataability/src/napi_data_ability_predicates.cpp b/relational_store/frameworks/js/napi/dataability/src/napi_data_ability_predicates.cpp index 848825b0..1089e67d 100644 --- a/relational_store/frameworks/js/napi/dataability/src/napi_data_ability_predicates.cpp +++ b/relational_store/frameworks/js/napi/dataability/src/napi_data_ability_predicates.cpp @@ -91,7 +91,11 @@ napi_value DataAbilityPredicatesProxy::New(napi_env env, napi_callback_info info NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &thiz, nullptr)); if (is_constructor) { - auto *proxy = new DataAbilityPredicatesProxy(); + auto *proxy = new (std::nothrow) DataAbilityPredicatesProxy(); + if (proxy == nullptr) { + LOG_ERROR("DataAbilityPredicatesProxy::New new failed, proxy is nullptr"); + return nullptr; + } napi_status status = napi_wrap(env, thiz, proxy, DataAbilityPredicatesProxy::Destructor, nullptr, nullptr); if (status != napi_ok) { LOG_ERROR("DataAbilityPredicatesProxy::New napi_wrap failed! napi_status:%{public}d!", status); diff --git a/relational_store/frameworks/js/napi/rdb/include/napi_rdb_error.h b/relational_store/frameworks/js/napi/rdb/include/napi_rdb_error.h index f4dda5a2..35430275 100644 --- a/relational_store/frameworks/js/napi/rdb/include/napi_rdb_error.h +++ b/relational_store/frameworks/js/napi/rdb/include/napi_rdb_error.h @@ -26,7 +26,6 @@ constexpr int APIVERSION_V9 = 9; constexpr int APIVERSION_8 = 8; constexpr int E_PARAM_ERROR = 401; - constexpr int E_INNER_ERROR = 14800000; constexpr int E_DB_INVALID = 14800010; @@ -42,7 +41,7 @@ constexpr int E_RESULT_GOTO_ERROR = 14800012; napi_throw_error((env), nullptr, "error message is empty"); \ return retVal; \ } \ - if (((version) > (APIVERSION_8)) || ((error->GetCode()) == (401))) { \ + if (((version) > (APIVERSION_8)) || ((error->GetCode()) == (401))) { \ LOG_ERROR("throw error: code = %{public}d , message = %{public}s, version= %{public}d", \ error->GetCode(), error->GetMessage().c_str(), version); \ napi_throw_error((env), std::to_string(error->GetCode()).c_str(), error->GetMessage().c_str()); \ diff --git a/relational_store/frameworks/js/napi/rdb/include/napi_rdb_store.h b/relational_store/frameworks/js/napi/rdb/include/napi_rdb_store.h index 9302486e..7cfcc6fb 100644 --- a/relational_store/frameworks/js/napi/rdb/include/napi_rdb_store.h +++ b/relational_store/frameworks/js/napi/rdb/include/napi_rdb_store.h @@ -49,10 +49,8 @@ private: 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 RemoteQuery(napi_env env, napi_callback_info info); static napi_value QuerySql(napi_env env, napi_callback_info info); static napi_value ExecuteSql(napi_env env, napi_callback_info info); - static napi_value Backup(napi_env env, napi_callback_info info); static napi_value Count(napi_env env, napi_callback_info info); static napi_value Replace(napi_env env, napi_callback_info info); static napi_value Attach(napi_env env, napi_callback_info info); @@ -68,7 +66,6 @@ private: 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 SetVersion(napi_env env, napi_callback_info info); - static napi_value Restore(napi_env env, napi_callback_info info); static napi_value SetDistributedTables(napi_env env, napi_callback_info info); static napi_value ObtainDistributedTableName(napi_env env, napi_callback_info info); static napi_value Sync(napi_env env, napi_callback_info info); diff --git a/relational_store/frameworks/js/napi/rdb/mock/include/napi_rdb_store.h b/relational_store/frameworks/js/napi/rdb/mock/include/napi_rdb_store.h index b0bad095..f0f862bb 100644 --- a/relational_store/frameworks/js/napi/rdb/mock/include/napi_rdb_store.h +++ b/relational_store/frameworks/js/napi/rdb/mock/include/napi_rdb_store.h @@ -49,7 +49,6 @@ private: 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 ExecuteSql(napi_env env, napi_callback_info info); - static napi_value Backup(napi_env env, napi_callback_info info); static napi_value Count(napi_env env, napi_callback_info info); static napi_value Replace(napi_env env, napi_callback_info info); static napi_value Attach(napi_env env, napi_callback_info info); @@ -65,7 +64,6 @@ private: 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 SetVersion(napi_env env, napi_callback_info info); - static napi_value Restore(napi_env env, napi_callback_info info); std::mutex mutex_; std::shared_ptr rdbStore_; }; diff --git a/relational_store/frameworks/js/napi/rdb/src/napi_rdb_predicates.cpp b/relational_store/frameworks/js/napi/rdb/src/napi_rdb_predicates.cpp index aa59249b..54160757 100644 --- a/relational_store/frameworks/js/napi/rdb/src/napi_rdb_predicates.cpp +++ b/relational_store/frameworks/js/napi/rdb/src/napi_rdb_predicates.cpp @@ -128,7 +128,11 @@ napi_value RdbPredicatesProxy::InnerNew(napi_env env, napi_callback_info info, i std::string tableName = JSUtils::Convert2String(env, args[0]); RDB_NAPI_ASSERT_FROMV9( env, !tableName.empty(), std::make_shared("name", "a non empty string."), version); - auto *proxy = new RdbPredicatesProxy(tableName); + auto *proxy = new (std::nothrow) RdbPredicatesProxy(tableName); + if (proxy == nullptr) { + LOG_ERROR("RdbPredicatesProxy::InnerNew new failed, proxy is nullptr"); + return nullptr; + } napi_status status = napi_wrap(env, thiz, proxy, RdbPredicatesProxy::Destructor, nullptr, nullptr); if (status != napi_ok) { LOG_ERROR("RdbPredicatesProxy::InnerNew napi_wrap failed! napi_status:%{public}d!", status); diff --git a/relational_store/frameworks/js/napi/rdb/src/napi_rdb_store.cpp b/relational_store/frameworks/js/napi/rdb/src/napi_rdb_store.cpp index e96585c4..80bb044c 100644 --- a/relational_store/frameworks/js/napi/rdb/src/napi_rdb_store.cpp +++ b/relational_store/frameworks/js/napi/rdb/src/napi_rdb_store.cpp @@ -157,12 +157,8 @@ void RdbStoreProxy::Init(napi_env env, napi_value exports) DECLARE_NAPI_FUNCTION("batchInsert", BatchInsert), DECLARE_NAPI_FUNCTION("querySql", QuerySql), DECLARE_NAPI_FUNCTION("query", Query), -#if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) - DECLARE_NAPI_FUNCTION("remoteQuery", RemoteQuery), -#endif DECLARE_NAPI_FUNCTION("executeSql", ExecuteSql), DECLARE_NAPI_FUNCTION("replace", Replace), - DECLARE_NAPI_FUNCTION("backup", Backup), DECLARE_NAPI_FUNCTION("count", Count), DECLARE_NAPI_FUNCTION("addAttach", Attach), DECLARE_NAPI_FUNCTION("beginTransaction", BeginTransaction), @@ -171,7 +167,6 @@ void RdbStoreProxy::Init(napi_env env, napi_value exports) DECLARE_NAPI_FUNCTION("queryByStep", QueryByStep), DECLARE_NAPI_FUNCTION("getVersion", GetVersion), DECLARE_NAPI_FUNCTION("setVersion", SetVersion), - DECLARE_NAPI_FUNCTION("restore", Restore), DECLARE_NAPI_GETTER("isInTransaction", IsInTransaction), DECLARE_NAPI_GETTER("isOpen", IsOpen), DECLARE_NAPI_GETTER("path", GetPath), @@ -757,45 +752,6 @@ napi_value RdbStoreProxy::Query(napi_env env, napi_callback_info info) return AsyncCall::Call(env, context); } -#if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) -napi_value RdbStoreProxy::RemoteQuery(napi_env env, napi_callback_info info) -{ - LOG_DEBUG("RdbStoreProxy::RemoteQuery start"); - auto context = std::make_shared(); - auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) -> int { - std::shared_ptr paramNumError = std::make_shared("4 or 5"); - RDB_CHECK_RETURN_CALL_RESULT(argc == 4 || argc == 5, context->SetError(paramNumError)); - RDB_ASYNC_PARAM_CHECK_FUNCTION(ParseDevice(env, argv[0], context)); - RDB_ASYNC_PARAM_CHECK_FUNCTION(ParseTableName(env, argv[1], context)); - RDB_ASYNC_PARAM_CHECK_FUNCTION(ParsePredicates(env, argv[2], context)); - RDB_ASYNC_PARAM_CHECK_FUNCTION(ParseColumns(env, argv[3], context)); - ParserThis(env, self, context); - return OK; - }; - auto exec = [context]() { - LOG_DEBUG("RdbStoreProxy::RemoteQuery Async"); - RdbStoreProxy *obj = reinterpret_cast(context->boundObj); - context->newResultSet = - obj->rdbStore_->RemoteQuery(context->device, *(context->rdbPredicates), context->columns); - LOG_DEBUG("RdbStoreProxy::RemoteQuery result is nullptr ? %{public}d", (context->newResultSet == nullptr)); - return (context->newResultSet != nullptr) ? OK : ERR; - }; - auto output = [context](napi_env env, napi_value &result) -> int { - if (context->newResultSet == nullptr) { - LOG_DEBUG("RdbStoreProxy::RemoteQuery result is nullptr"); - return ERR; - } - result = ResultSetProxy::NewInstance(env, context->newResultSet, context->apiversion); - LOG_DEBUG("RdbStoreProxy::RemoteQuery end"); - return (result != nullptr) ? OK : ERR; - }; - context->SetAction(env, info, input, exec, output); - - RDB_CHECK_RETURN_NULLPTR(context->error == nullptr || context->error->GetCode() == OK); - return AsyncCall::Call(env, context); -} -#endif - napi_value RdbStoreProxy::QuerySql(napi_env env, napi_callback_info info) { DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__)); @@ -947,35 +903,6 @@ napi_value RdbStoreProxy::Replace(napi_env env, napi_callback_info info) return AsyncCall::Call(env, context); } -napi_value RdbStoreProxy::Backup(napi_env env, napi_callback_info info) -{ - LOG_DEBUG("RdbStoreProxy::Backup start"); - auto context = std::make_shared(); - auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) -> int { - std::shared_ptr paramNumError = std::make_shared("1 or 2"); - RDB_CHECK_RETURN_CALL_RESULT(argc == 1 || argc == 2, context->SetError(paramNumError)); - RDB_ASYNC_PARAM_CHECK_FUNCTION(ParseTableName(env, argv[0], context)); - ParserThis(env, self, context); - return OK; - }; - auto exec = [context]() { - LOG_DEBUG("RdbStoreProxy::Backup Async"); - RdbStoreProxy *obj = reinterpret_cast(context->boundObj); - int errCode = obj->rdbStore_->Backup(context->tableName, context->newKey); - LOG_DEBUG("RdbStoreProxy::Backup errCode is: %{public}d", errCode); - return (errCode == E_OK) ? OK : ERR; - }; - auto output = [context](napi_env env, napi_value &result) -> int { - napi_status status = napi_get_undefined(env, &result); - LOG_DEBUG("RdbStoreProxy::Backup end"); - return (status == napi_ok) ? OK : ERR; - }; - context->SetAction(env, info, input, exec, output); - - RDB_CHECK_RETURN_NULLPTR(context->error == nullptr || context->error->GetCode() == OK); - return AsyncCall::Call(env, context); -} - napi_value RdbStoreProxy::Attach(napi_env env, napi_callback_info info) { LOG_DEBUG("RdbStoreProxy::Attach start"); @@ -1171,36 +1098,6 @@ napi_value RdbStoreProxy::SetVersion(napi_env env, napi_callback_info info) return nullptr; } -napi_value RdbStoreProxy::Restore(napi_env env, napi_callback_info info) -{ - LOG_DEBUG("RdbStoreProxy::Restore start"); - auto context = std::make_shared(); - auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) -> int { - std::shared_ptr paramNumError = std::make_shared("1 or 2"); - RDB_CHECK_RETURN_CALL_RESULT(argc == 1 || argc == 2, context->SetError(paramNumError)); - RDB_ASYNC_PARAM_CHECK_FUNCTION(ParseSrcName(env, argv[0], context)); - ParserThis(env, self, context); - return OK; - }; - auto exec = [context]() { - LOG_DEBUG("RdbStoreProxy::Restore Async"); - RdbStoreProxy *obj = reinterpret_cast(context->boundObj); - int errCode = 0; - errCode = obj->rdbStore_->Restore(context->srcName, context->newKey); - LOG_DEBUG("RdbStoreProxy::Restore errCode is : %{public}d", errCode); - return (errCode == E_OK) ? OK : ERR; - }; - auto output = [context](napi_env env, napi_value &result) -> int { - napi_status status = napi_get_undefined(env, &result); - LOG_DEBUG("RdbStoreProxy::Restore end"); - return (status == napi_ok) ? OK : ERR; - }; - context->SetAction(env, info, input, exec, output); - - RDB_CHECK_RETURN_NULLPTR(context->error == nullptr || context->error->GetCode() == OK); - return AsyncCall::Call(env, context); -} - #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) napi_value RdbStoreProxy::SetDistributedTables(napi_env env, napi_callback_info info) { @@ -1216,9 +1113,9 @@ napi_value RdbStoreProxy::SetDistributedTables(napi_env env, napi_callback_info auto exec = [context]() { LOG_DEBUG("RdbStoreProxy::SetDistributedTables Async"); RdbStoreProxy *obj = reinterpret_cast(context->boundObj); - bool res = obj->rdbStore_->SetDistributedTables(context->tablesName); + int res = obj->rdbStore_->SetDistributedTables(context->tablesName); LOG_DEBUG("RdbStoreProxy::SetDistributedTables res is : %{public}d", res); - return res ? OK : ERR; + return res == E_OK ? OK : ERR; }; auto output = [context](napi_env env, napi_value &result) -> int { napi_status status = napi_get_undefined(env, &result); @@ -1246,8 +1143,10 @@ napi_value RdbStoreProxy::ObtainDistributedTableName(napi_env env, napi_callback auto exec = [context]() { LOG_DEBUG("RdbStoreProxy::ObtainDistributedTableName Async"); RdbStoreProxy *obj = reinterpret_cast(context->boundObj); - auto name = obj->rdbStore_->ObtainDistributedTableName(context->device, context->tableName); - LOG_INFO("RdbStoreProxy::ObtainDistributedTableName name is empty ? : %{public}d", name.empty()); + int errCode = E_ERROR; + auto name = obj->rdbStore_->ObtainDistributedTableName(context->device, context->tableName, errCode); + LOG_INFO("RdbStoreProxy::ObtainDistributedTableName name is empty ? : %{public}d, errCode is %{public}d", + name.empty(), errCode); context->tableName = name; return name.empty() ? ERR : OK; }; @@ -1281,10 +1180,10 @@ napi_value RdbStoreProxy::Sync(napi_env env, napi_callback_info info) SyncOption option; option.mode = static_cast(context->enumArg); option.isBlock = true; - bool res = obj->rdbStore_->Sync(option, *context->predicatesProxy->GetPredicates(), + int res = obj->rdbStore_->Sync(option, *context->predicatesProxy->GetPredicates(), [context](const SyncResult &result) { context->syncResult = result; }); LOG_INFO("RdbStoreProxy::Sync res is : %{public}d", res); - return res ? OK : ERR; + return res == E_OK ? OK : ERR; }; auto output = [context](napi_env env, napi_value &result) -> int { result = JSUtils::Convert2JSValue(env, context->syncResult); @@ -1329,7 +1228,8 @@ void RdbStoreProxy::OnDataChangeEvent(napi_env env, size_t argc, napi_value *arg SubscribeOption option; option.mode = static_cast(mode); auto observer = std::make_shared(env, argv[1]); - if (!rdbStore_->Subscribe(option, observer.get())) { + int errCode = rdbStore_->Subscribe(option, observer.get()); + if (errCode != E_OK) { LOG_ERROR("RdbStoreProxy::OnDataChangeEvent: subscribe failed"); return; } diff --git a/relational_store/frameworks/js/napi/rdb/src/napi_result_set.cpp b/relational_store/frameworks/js/napi/rdb/src/napi_result_set.cpp index 5ed14e1e..87dd8a47 100644 --- a/relational_store/frameworks/js/napi/rdb/src/napi_result_set.cpp +++ b/relational_store/frameworks/js/napi/rdb/src/napi_result_set.cpp @@ -163,7 +163,11 @@ napi_value ResultSetProxy::InnerInitialize(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 ResultSetProxy(); + auto *proxy = new (std::nothrow) ResultSetProxy(); + if (proxy == nullptr) { + LOG_ERROR("ResultSetProxy::InnerInitialize new failed, proxy is nullptr"); + return nullptr; + } proxy->apiversion = version; auto finalize = [](napi_env env, void *data, void *hint) { ResultSetProxy *proxy = reinterpret_cast(data); diff --git a/relational_store/frameworks/js/napi/rdb/src/napi_values_bucket.cpp b/relational_store/frameworks/js/napi/rdb/src/napi_values_bucket.cpp index 327ad774..1480ba52 100644 --- a/relational_store/frameworks/js/napi/rdb/src/napi_values_bucket.cpp +++ b/relational_store/frameworks/js/napi/rdb/src/napi_values_bucket.cpp @@ -27,8 +27,7 @@ __attribute__((visibility("default"))) napi_value NAPI_OHOS_Data_RdbJsKit_Values { napi_value ret; NAPI_CALL(env, napi_create_object(env, &ret)); - std::map valuesMap; - valuesBucket.GetAll(valuesMap); + std::map valuesMap = valuesBucket.GetAll(); std::map::iterator it; for (it = valuesMap.begin(); it != valuesMap.end(); ++it) { std::string key = it->first; @@ -73,7 +72,11 @@ __attribute__((visibility("default"))) napi_value NAPI_OHOS_Data_RdbJsKit_Values __attribute__((visibility("default"))) ValuesBucket *NAPI_OHOS_Data_RdbJsKit_ValuesBucketProxy_GetNativeObject( napi_env env, napi_value &arg) { - ValuesBucket *valuesBucket = new ValuesBucket; + ValuesBucket *valuesBucket = new (std::nothrow) ValuesBucket; + if (valuesBucket == nullptr) { + LOG_ERROR("ValuesBucket new failed, valuesBucket is nullptr"); + return nullptr; + } napi_value keys = 0; napi_get_property_names(env, arg, &keys); uint32_t arrLen = 0; diff --git a/relational_store/frameworks/js/napi/relationalstore/include/napi_rdb_error.h b/relational_store/frameworks/js/napi/relationalstore/include/napi_rdb_error.h index f0ef6f7d..37ba8fd3 100644 --- a/relational_store/frameworks/js/napi/relationalstore/include/napi_rdb_error.h +++ b/relational_store/frameworks/js/napi/relationalstore/include/napi_rdb_error.h @@ -36,6 +36,7 @@ const static std::map ERROR_MAPS = { { NativeRdb::E_WAL_SIZE_OVER_LIMIT, "The WAL file size over default limit." }, { NativeRdb::E_EMPTY_FILE_NAME, "Failed to open database by database corrupted." }, { NativeRdb::E_INVALID_FILE_PATH, "Failed to open database by database corrupted" }, + { NativeRdb::E_NOT_SUPPORTED, "Capability not supported" }, { E_RESULT_GOTO_ERROR, "The result set is empty or the specified location is invalid." }, { E_RESULT_GET_ERROR, "The column value is null or the column type is incompatible." }, }; diff --git a/relational_store/frameworks/js/napi/relationalstore/include/napi_rdb_store.h b/relational_store/frameworks/js/napi/relationalstore/include/napi_rdb_store.h index 7ee32277..7be65cf4 100644 --- a/relational_store/frameworks/js/napi/relationalstore/include/napi_rdb_store.h +++ b/relational_store/frameworks/js/napi/relationalstore/include/napi_rdb_store.h @@ -75,8 +75,8 @@ private: static constexpr int MIN_ON_EVENT_ARG_NUM = 2; static constexpr int MAX_ON_EVENT_ARG_NUM = 5; - void OnDataChangeEvent(napi_env env, size_t argc, napi_value *argv); - void OffDataChangeEvent(napi_env env, size_t argc, napi_value *argv); + int OnDataChangeEvent(napi_env env, size_t argc, napi_value *argv); + int OffDataChangeEvent(napi_env env, size_t argc, napi_value *argv); std::mutex mutex_; bool isSystemAppCalled_ = false; diff --git a/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_predicates.cpp b/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_predicates.cpp index 4d30a1c5..2eb54a2a 100644 --- a/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_predicates.cpp +++ b/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_predicates.cpp @@ -101,7 +101,11 @@ napi_value RdbPredicatesProxy::New(napi_env env, napi_callback_info info) RDB_NAPI_ASSERT(env, valueType == napi_string, std::make_shared("name", "not empty")); std::string tableName = JSUtils::Convert2String(env, args[0]); RDB_NAPI_ASSERT(env, !tableName.empty(), std::make_shared("name", "not empty")); - auto *proxy = new RdbPredicatesProxy(tableName); + auto *proxy = new (std::nothrow) RdbPredicatesProxy(tableName); + if (proxy == nullptr) { + LOG_ERROR("RdbPredicatesProxy::New new failed, proxy is nullptr"); + return nullptr; + } napi_status status = napi_wrap(env, thiz, proxy, RdbPredicatesProxy::Destructor, nullptr, nullptr); if (status != napi_ok) { LOG_ERROR("RdbPredicatesProxy::New napi_wrap failed! napi_status:%{public}d!", status); diff --git a/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_store.cpp b/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_store.cpp index c10e46ba..d9aed0e3 100644 --- a/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_store.cpp +++ b/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_store.cpp @@ -81,7 +81,7 @@ struct RdbStoreContext : public Context { std::shared_ptr rdbPredicates = nullptr; RdbStoreContext() - : predicatesProxy(nullptr), int64Output(0), intOutput(0), enumArg(0), + : predicatesProxy(nullptr), int64Output(0), intOutput(0), enumArg(-1), conflictResolution(NativeRdb::ConflictResolution::ON_CONFLICT_NONE) { } @@ -276,7 +276,11 @@ int ParseTablesName(const napi_env &env, const napi_value &arg, std::shared_ptr< int ParseSyncModeArg(const napi_env &env, const napi_value &arg, std::shared_ptr context) { - napi_get_value_int32(env, arg, &context->enumArg); + napi_valuetype type = napi_undefined; + napi_typeof(env, arg, &type); + CHECK_RETURN_SET(type == napi_number, std::make_shared("mode", "a SyncMode Type.")); + napi_status status = napi_get_value_int32(env, arg, &context->enumArg); + CHECK_RETURN_SET(status == napi_ok, std::make_shared("mode", "a SyncMode Type.")); bool checked = context->enumArg == 0 || context->enumArg == 1; CHECK_RETURN_SET(checked, std::make_shared("mode", "a SyncMode.")); @@ -622,10 +626,11 @@ napi_value RdbStoreProxy::RemoteQuery(napi_env env, napi_callback_info info) auto exec = [context]() -> int { LOG_DEBUG("RdbStoreProxy::RemoteQuery Async"); RdbStoreProxy *obj = reinterpret_cast(context->boundObj); + int errCode = E_ERROR; context->newResultSet = - obj->rdbStore_->RemoteQuery(context->device, *(context->rdbPredicates), context->columns); - LOG_DEBUG("RdbStoreProxy::RemoteQuery result is nullptr ? %{public}d", (context->newResultSet == nullptr)); - return (context->newResultSet != nullptr) ? E_OK : E_ERROR; + obj->rdbStore_->RemoteQuery(context->device, *(context->rdbPredicates), context->columns, errCode); + LOG_DEBUG("RemoteQuerry ret is %{public}d.", errCode); + return errCode; }; auto output = [context](napi_env env, napi_value &result) { result = ResultSetProxy::NewInstance(env, context->newResultSet); @@ -1061,7 +1066,7 @@ napi_value RdbStoreProxy::SetDistributedTables(napi_env env, napi_callback_info auto exec = [context]() -> int { LOG_DEBUG("RdbStoreProxy::SetDistributedTables Async"); RdbStoreProxy *obj = reinterpret_cast(context->boundObj); - return obj->rdbStore_->SetDistributedTables(context->tablesNames) ? E_OK : E_ERROR; + return obj->rdbStore_->SetDistributedTables(context->tablesNames); }; auto output = [context](napi_env env, napi_value &result) { napi_status status = napi_get_undefined(env, &result); @@ -1087,8 +1092,9 @@ napi_value RdbStoreProxy::ObtainDistributedTableName(napi_env env, napi_callback auto exec = [context]() -> int { LOG_DEBUG("RdbStoreProxy::ObtainDistributedTableName Async"); RdbStoreProxy *obj = reinterpret_cast(context->boundObj); - context->tableName = obj->rdbStore_->ObtainDistributedTableName(context->device, context->tableName); - return context->tableName.empty() ? E_OK : E_ERROR; + int errCode = E_ERROR; + context->tableName = obj->rdbStore_->ObtainDistributedTableName(context->device, context->tableName, errCode); + return errCode; }; auto output = [context](napi_env env, napi_value &result) { std::string table = context->tableName; @@ -1118,10 +1124,8 @@ napi_value RdbStoreProxy::Sync(napi_env env, napi_callback_info info) SyncOption option; option.mode = static_cast(context->enumArg); option.isBlock = true; - bool res = obj->rdbStore_->Sync(option, *context->predicatesProxy->GetPredicates(), + return obj->rdbStore_->Sync(option, *context->predicatesProxy->GetPredicates(), [context](const SyncResult &result) { context->syncResult = result; }); - LOG_INFO("RdbStoreProxy::Sync res is : %{public}d", res); - return res ? E_OK : E_ERROR; }; auto output = [context](napi_env env, napi_value &result) { result = JSUtils::Convert2JSValue(env, context->syncResult); @@ -1134,26 +1138,26 @@ napi_value RdbStoreProxy::Sync(napi_env env, napi_callback_info info) return AsyncCall::Call(env, context); } -void RdbStoreProxy::OnDataChangeEvent(napi_env env, size_t argc, napi_value *argv) +int RdbStoreProxy::OnDataChangeEvent(napi_env env, size_t argc, napi_value *argv) { napi_valuetype type; napi_typeof(env, argv[0], &type); if (type != napi_number) { LOG_ERROR("RdbStoreProxy::OnDataChangeEvent: first argument is not number"); - return; + return ERR; } int32_t mode = SubscribeMode::SUBSCRIBE_MODE_MAX; napi_get_value_int32(env, argv[0], &mode); if (mode < 0 || mode >= SubscribeMode::SUBSCRIBE_MODE_MAX) { LOG_ERROR("RdbStoreProxy::OnDataChangeEvent: first argument value is invalid"); - return; + return ERR; } LOG_INFO("RdbStoreProxy::OnDataChangeEvent: mode=%{public}d", mode); napi_typeof(env, argv[1], &type); if (type != napi_function) { LOG_ERROR("RdbStoreProxy::OnDataChangeEvent: second argument is not function"); - return; + return ERR; } std::lock_guard lockGuard(mutex_); @@ -1162,39 +1166,38 @@ void RdbStoreProxy::OnDataChangeEvent(napi_env env, size_t argc, napi_value *arg }); if (result) { LOG_ERROR("RdbStoreProxy::OnDataChangeEvent: duplicate subscribe"); - return; + return ERR; } SubscribeOption option; option.mode = static_cast(mode); auto observer = std::make_shared(env, argv[1]); - if (!rdbStore_->Subscribe(option, observer.get())) { - LOG_ERROR("RdbStoreProxy::OnDataChangeEvent: subscribe failed"); - return; - } + int errCode = rdbStore_->Subscribe(option, observer.get()); + LOG_DEBUG("Subscribe ret is %{public}d.", errCode); + RDB_NAPI_ASSERT_BASE(env, errCode == E_OK, std::make_shared(errCode), ERR); observers_[mode].push_back(observer); - LOG_ERROR("RdbStoreProxy::OnDataChangeEvent: subscribe success"); + return OK; } -void RdbStoreProxy::OffDataChangeEvent(napi_env env, size_t argc, napi_value *argv) +int RdbStoreProxy::OffDataChangeEvent(napi_env env, size_t argc, napi_value *argv) { napi_valuetype type; napi_typeof(env, argv[0], &type); if (type != napi_number) { LOG_ERROR("RdbStoreProxy::OffDataChangeEvent: first argument is not number"); - return; + return ERR; } int32_t mode = SubscribeMode::SUBSCRIBE_MODE_MAX; napi_get_value_int32(env, argv[0], &mode); if (mode < 0 || mode >= SubscribeMode::SUBSCRIBE_MODE_MAX) { LOG_ERROR("RdbStoreProxy::OffDataChangeEvent: first argument value is invalid"); - return; + return ERR; } LOG_INFO("RdbStoreProxy::OffDataChangeEvent: mode=%{public}d", mode); napi_typeof(env, argv[1], &type); if (type != napi_function) { LOG_ERROR("RdbStoreProxy::OffDataChangeEvent: second argument is not function"); - return; + return ERR; } SubscribeOption option; @@ -1202,13 +1205,15 @@ void RdbStoreProxy::OffDataChangeEvent(napi_env env, size_t argc, napi_value *ar std::lock_guard lockGuard(mutex_); for (auto it = observers_[mode].begin(); it != observers_[mode].end(); it++) { if (**it == argv[1]) { - rdbStore_->UnSubscribe(option, it->get()); + int errCode = rdbStore_->UnSubscribe(option, it->get()); observers_[mode].erase(it); - LOG_INFO("RdbStoreProxy::OffDataChangeEvent: unsubscribe success"); - return; + LOG_INFO("unsubscribe err is %{public}d.", errCode); + RDB_NAPI_ASSERT_BASE(env, errCode == E_OK, std::make_shared(errCode), ERR); + return OK; } } LOG_INFO("RdbStoreProxy::OffDataChangeEvent: not found"); + return ERR; } napi_value RdbStoreProxy::OnEvent(napi_env env, napi_callback_info info) @@ -1228,7 +1233,9 @@ napi_value RdbStoreProxy::OnEvent(napi_env env, napi_callback_info info) std::string event = JSUtils::Convert2String(env, argv[0]); if (event == "dataChange") { - proxy->OnDataChangeEvent(env, argc - 1, argv + 1); + if (proxy->OnDataChangeEvent(env, argc - 1, argv + 1) != OK) { + return nullptr; + } } LOG_INFO("RdbStoreProxy::OnEvent end"); @@ -1252,7 +1259,9 @@ napi_value RdbStoreProxy::OffEvent(napi_env env, napi_callback_info info) std::string event = JSUtils::Convert2String(env, argv[0]); if (event == "dataChange") { - proxy->OffDataChangeEvent(env, argc - 1, argv + 1); + if (proxy->OffDataChangeEvent(env, argc - 1, argv + 1) != OK) { + return nullptr; + } } LOG_INFO("RdbStoreProxy::OffEvent end"); diff --git a/relational_store/frameworks/js/napi/relationalstore/src/napi_result_set.cpp b/relational_store/frameworks/js/napi/relationalstore/src/napi_result_set.cpp index ed36e5ad..de7a07eb 100644 --- a/relational_store/frameworks/js/napi/relationalstore/src/napi_result_set.cpp +++ b/relational_store/frameworks/js/napi/relationalstore/src/napi_result_set.cpp @@ -115,7 +115,11 @@ napi_value ResultSetProxy::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 ResultSetProxy(); + auto *proxy = new (std::nothrow) ResultSetProxy(); + if (proxy == nullptr) { + LOG_ERROR("ResultSetProxy::Initialize new failed, proxy is nullptr"); + return nullptr; + } auto finalize = [](napi_env env, void *data, void *hint) { ResultSetProxy *proxy = reinterpret_cast(data); delete proxy; diff --git a/relational_store/frameworks/native/appdatafwk/src/shared_block.cpp b/relational_store/frameworks/native/appdatafwk/src/shared_block.cpp index b4d312e1..855c9e1c 100644 --- a/relational_store/frameworks/native/appdatafwk/src/shared_block.cpp +++ b/relational_store/frameworks/native/appdatafwk/src/shared_block.cpp @@ -37,7 +37,6 @@ SharedBlock::~SharedBlock() if (ashmem_ != nullptr) { ashmem_->UnmapAshmem(); ashmem_->CloseAshmem(); - LOG_WARN("SharedBlock: close ashmem"); } } diff --git a/relational_store/frameworks/native/rdb/include/rdb_manager.h b/relational_store/frameworks/native/rdb/include/rdb_manager.h index 07185fbb..5167069a 100644 --- a/relational_store/frameworks/native/rdb/include/rdb_manager.h +++ b/relational_store/frameworks/native/rdb/include/rdb_manager.h @@ -26,7 +26,7 @@ namespace OHOS::DistributedRdb { class RdbManager { public: - static std::shared_ptr GetRdbService(const RdbSyncerParam& param); + static int GetRdbService(const RdbSyncerParam& param, std::shared_ptr &service); }; } // namespace OHOS::DistributedRdb #endif diff --git a/relational_store/frameworks/native/rdb/include/rdb_manager_impl.h b/relational_store/frameworks/native/rdb/include/rdb_manager_impl.h index f2c20f3e..13e5ea0b 100644 --- a/relational_store/frameworks/native/rdb/include/rdb_manager_impl.h +++ b/relational_store/frameworks/native/rdb/include/rdb_manager_impl.h @@ -39,7 +39,7 @@ public: static RdbManagerImpl &GetInstance(); - std::shared_ptr GetRdbService(const RdbSyncerParam& param); + int GetRdbService(const RdbSyncerParam& param, std::shared_ptr &service); void OnRemoteDied(); @@ -61,8 +61,6 @@ private: ~RdbManagerImpl(); - sptr GetRdbService(); - void ResetServiceHandle(); static std::shared_ptr GetDistributedDataManager(); diff --git a/relational_store/frameworks/native/rdb/include/rdb_security_manager.h b/relational_store/frameworks/native/rdb/include/rdb_security_manager.h index 1bed52ff..c2e880b6 100644 --- a/relational_store/frameworks/native/rdb/include/rdb_security_manager.h +++ b/relational_store/frameworks/native/rdb/include/rdb_security_manager.h @@ -49,6 +49,7 @@ public: RdbPassword(); ~RdbPassword(); + bool isKeyExpired = false; bool operator==(const RdbPassword &input) const; bool operator!=(const RdbPassword &input) const; @@ -56,6 +57,7 @@ public: const uint8_t *GetData() const; int SetValue(const uint8_t *inputData, size_t inputSize); int Clear(); + bool IsValid() const; private: static constexpr size_t MAX_PASSWORD_SIZE = 128; @@ -65,18 +67,19 @@ private: class RdbSecurityManager { public: - enum class KeyFileType { PUB_KEY_FILE = 1, PUB_KEY_BAK_FILE }; + enum class KeyFileType { + PUB_KEY_FILE = 1, + PUB_KEY_FILE_NEW_KEY + }; RdbPassword GetRdbPassword(KeyFileType keyFile); void DelRdbSecretDataFile(const std::string &path); - bool CheckKeyDataFileExists(RdbSecurityManager::KeyFileType keyFile); - bool SaveSecretKeyToFile(RdbSecurityManager::KeyFileType keyFile, const std::vector &key); + void DelRdbSecretDataFile(RdbSecurityManager::KeyFileType keyFile); static RdbSecurityManager &GetInstance(); int GetKeyDistributedStatus(KeyFileType keyFile, bool &status); int SetKeyDistributedStatus(KeyFileType keyFile, bool status); void Init(const std::string &bundleName, const std::string &path); - std::vector GenerateRandomNum(int32_t len); - static constexpr int RDB_KEY_SIZE = 32; + void UpdateKeyFile(); private: RdbSecurityManager(); @@ -89,9 +92,14 @@ private: std::vector GenerateRootKeyAlias(const std::string &bundleName); bool InitPath(const std::string &path); void ParsePath(const std::string &path); + bool CheckKeyDataFileExists(RdbSecurityManager::KeyFileType keyFile); + std::vector GenerateRandomNum(int32_t len); + bool SaveSecretKeyToFile(RdbSecurityManager::KeyFileType keyFile); bool SaveSecretKeyToDisk(const std::string &path, RdbSecretKeyData &keyData); + RdbPassword LoadSecretKeyFromFile(KeyFileType keyFile); bool LoadSecretKeyFromDisk(const std::string &keyPath, RdbSecretKeyData &keyData); - bool IsKeyOutOfdate(const time_t &createTime) const; + static bool IsKeyExpired(const time_t &createTime) ; + void GetKeyPath(KeyFileType keyType, std::string &keyPath); int32_t MallocAndCheckBlobData(struct HksBlob *blob, const uint32_t blobSize); int32_t HksLoopUpdate(const struct HksBlob *handle, const struct HksParamSet *paramSet, const struct HksBlob *inData, struct HksBlob *outData); @@ -101,7 +109,7 @@ private: const struct HksBlob *cipherText, struct HksBlob *plainText); static constexpr char const *SUFFIX_PUB_KEY = ".pub_key"; - static constexpr char const *SUFFIX_PUB_KEY_BAK = ".pub_key_bak"; + static constexpr char const *SUFFIX_PUB_KEY_NEW = ".pub_key.new"; static constexpr const char *RDB_ROOT_KEY_ALIAS_PREFIX = "DistributedDataRdb"; static constexpr const char *RDB_HKS_BLOB_TYPE_NONCE = "Z5s0Bo571Koq"; static constexpr const char *RDB_HKS_BLOB_TYPE_AAD = "RdbClientAAD"; @@ -109,13 +117,14 @@ private: static const uint32_t MAX_UPDATE_SIZE = 64; static const uint32_t MAX_OUTDATA_SIZE = MAX_UPDATE_SIZE * TIMES; static const uint8_t AEAD_LEN = 16; + static constexpr int RDB_KEY_SIZE = 32; std::string bundleName_; std::string dbDir_; std::string dbName_; std::string dbKeyDir_; std::string keyPath_; - std::string keyBakPath_; + std::string newKeyPath_; static constexpr int HOURS_PER_YEAR = (24 * 365); static constexpr uint8_t UNDISTRIBUTED = 0; diff --git a/relational_store/frameworks/native/rdb/include/rdb_store_impl.h b/relational_store/frameworks/native/rdb/include/rdb_store_impl.h index df19a713..149ac934 100644 --- a/relational_store/frameworks/native/rdb/include/rdb_store_impl.h +++ b/relational_store/frameworks/native/rdb/include/rdb_store_impl.h @@ -26,7 +26,6 @@ #include "rdb_store_config.h" #include "sqlite_connection_pool.h" #include "sqlite_statement.h" -#include "store_session.h" #include "transaction_observer.h" namespace OHOS::NativeRdb { @@ -98,17 +97,17 @@ public: int Delete(int &deletedRows, const AbsRdbPredicates &predicates) override; std::shared_ptr RemoteQuery(const std::string &device, const AbsRdbPredicates &predicates, - const std::vector &columns) override; + const std::vector &columns, int &errCode) override; - bool SetDistributedTables(const std::vector& tables) override; + int SetDistributedTables(const std::vector& tables) override; - std::string ObtainDistributedTableName(const std::string& device, const std::string& table) override; + std::string ObtainDistributedTableName(const std::string& device, const std::string& table, int &errCode) override; - bool Sync(const SyncOption& option, const AbsRdbPredicates& predicate, const SyncCallback& callback) override; + int Sync(const SyncOption& option, const AbsRdbPredicates& predicate, const SyncCallback& callback) override; - bool Subscribe(const SubscribeOption& option, RdbStoreObserver *observer) override; + int Subscribe(const SubscribeOption& option, RdbStoreObserver *observer) override; - bool UnSubscribe(const SubscribeOption& option, RdbStoreObserver *observer) override; + int UnSubscribe(const SubscribeOption& option, RdbStoreObserver *observer) override; // user must use UDID bool DropDeviceData(const std::vector& devices, const DropOption& option) override; @@ -124,8 +123,6 @@ private: SqliteConnectionPool *connectionPool; static const int MAX_IDLE_SESSION_SIZE = 5; std::mutex sessionMutex; - std::map, int>> threadMap; - std::list> idleSessions; bool isOpen; std::string path; std::string orgPath; diff --git a/relational_store/frameworks/native/rdb/include/rdb_types_util.h b/relational_store/frameworks/native/rdb/include/rdb_types_util.h index 018a78f2..71dcf135 100644 --- a/relational_store/frameworks/native/rdb/include/rdb_types_util.h +++ b/relational_store/frameworks/native/rdb/include/rdb_types_util.h @@ -19,6 +19,7 @@ #include "rdb_types.h" #include "value_object.h" #include "values_bucket.h" +#include "rdb_visibility.h" namespace OHOS::ITypesUtil { using SyncerParam = DistributedRdb::RdbSyncerParam; using SyncOption = DistributedRdb::SyncOption; @@ -26,6 +27,7 @@ using RdbPredicates = DistributedRdb::RdbPredicates; using RdbOperation = DistributedRdb::RdbPredicateOperation; using ValueObject = NativeRdb::ValueObject; using ValuesBucket = NativeRdb::ValuesBucket; +using Asset = NativeRdb::AssetValue; template<> RDB_API_EXPORT bool Marshalling(const SyncerParam &input, MessageParcel &data); template<> @@ -50,5 +52,9 @@ template<> bool Marshalling(const ValuesBucket &input, MessageParcel &data); template<> bool Unmarshalling(ValuesBucket &output, MessageParcel &data); +template<> +bool Marshalling(const Asset &input, MessageParcel &data); +template<> +bool Unmarshalling(Asset &output, MessageParcel &data); } #endif // DISTRIBUTED_RDB_RDB_TYPES_UTIL_H diff --git a/relational_store/frameworks/native/rdb/include/sqlite_config.h b/relational_store/frameworks/native/rdb/include/sqlite_config.h index 607de29e..2cc9e041 100644 --- a/relational_store/frameworks/native/rdb/include/sqlite_config.h +++ b/relational_store/frameworks/native/rdb/include/sqlite_config.h @@ -35,7 +35,7 @@ public: std::string GetSyncMode() const; std::string GetDatabaseFileType() const; bool IsReadOnly() const; - bool IsEncrypt() const; + bool IsAutoEncrypt() const; std::string GetBundleName() const; bool IsCreateNecessary() const; void SetCreateNecessary(bool CreateNecessary); @@ -49,8 +49,12 @@ public: void SetEncryptAlgo(const std::string &encryptAlgo); int GetReadConSize() const; void SetReadConSize(int readConSize); + void SetEncryptKey(const std::vector &encryptKey); + std::vector GetEncryptKey() const; private: + void ClearEncryptKey(); + std::string path; StorageMode storageMode; std::string journalMode; @@ -65,6 +69,7 @@ private: // Encryption bool isEncrypt = false; + std::vector encryptKey_{}; std::string bundleName; bool isCreateNecessary; }; diff --git a/relational_store/frameworks/native/rdb/include/sqlite_connection.h b/relational_store/frameworks/native/rdb/include/sqlite_connection.h index ea982794..e44082a3 100644 --- a/relational_store/frameworks/native/rdb/include/sqlite_connection.h +++ b/relational_store/frameworks/native/rdb/include/sqlite_connection.h @@ -64,16 +64,13 @@ private: int Config(const SqliteConfig &config); int SetPageSize(const SqliteConfig &config); int SetEncryptAlgo(const SqliteConfig &config); - int SetEncryptKey(const std::vector &encryptKey); + int SetEncryptKey(const SqliteConfig &config); int SetJournalMode(const SqliteConfig &config); int SetJournalSizeLimit(const SqliteConfig &config); int SetAutoCheckpoint(const SqliteConfig &config); int SetWalSyncMode(const std::string &syncMode); int PrepareAndBind(const std::string &sql, const std::vector &bindArgs); void LimitPermission(const std::string &dbPath) const; - int ManageKey(const SqliteConfig &config); - int InitKey(); - int GetKeyFromFile(); int SetPersistWal(); int SetBusyTimeout(int timeout); diff --git a/relational_store/frameworks/native/rdb/include/sqlite_connection_pool.h b/relational_store/frameworks/native/rdb/include/sqlite_connection_pool.h index 6a283a61..f3dbc0a8 100644 --- a/relational_store/frameworks/native/rdb/include/sqlite_connection_pool.h +++ b/relational_store/frameworks/native/rdb/include/sqlite_connection_pool.h @@ -44,7 +44,7 @@ public: int ChangeDbFileForRestore(const std::string newPath, const std::string backupPath, const std::vector &newKey); std::stack &getTransactionStack(); - void AcquireTransaction(); + int AcquireTransaction(); void ReleaseTransaction(); private: diff --git a/relational_store/frameworks/native/rdb/include/sqlite_shared_result_set.h b/relational_store/frameworks/native/rdb/include/sqlite_shared_result_set.h index 199653da..7928de31 100644 --- a/relational_store/frameworks/native/rdb/include/sqlite_shared_result_set.h +++ b/relational_store/frameworks/native/rdb/include/sqlite_shared_result_set.h @@ -52,7 +52,6 @@ protected: private: int PrepareStep(); - int CheckSession(); void FillSharedBlock(int requiredPos); private: diff --git a/relational_store/frameworks/native/rdb/include/sqlite_utils.h b/relational_store/frameworks/native/rdb/include/sqlite_utils.h index 0a394100..f5264d71 100644 --- a/relational_store/frameworks/native/rdb/include/sqlite_utils.h +++ b/relational_store/frameworks/native/rdb/include/sqlite_utils.h @@ -43,6 +43,7 @@ public: static std::string StrToUpper(std::string s); static bool DeleteFile(const std::string path); static int RenameFile(const std::string srcFile, const std::string destFile); + static std::string Anonymous(const std::string &srcFile); static int GetFileSize(const std::string fileName); private: diff --git a/relational_store/frameworks/native/rdb/include/step_result_set.h b/relational_store/frameworks/native/rdb/include/step_result_set.h index 9a7c1fd8..721405a2 100644 --- a/relational_store/frameworks/native/rdb/include/step_result_set.h +++ b/relational_store/frameworks/native/rdb/include/step_result_set.h @@ -54,7 +54,6 @@ public: int PrepareStep(); private: - int CheckSession(); void Reset(); std::shared_ptr rdb; std::string sql; diff --git a/relational_store/frameworks/native/rdb/mock/include/rdb_store_impl.h b/relational_store/frameworks/native/rdb/mock/include/rdb_store_impl.h index efd7f3dd..765306a8 100644 --- a/relational_store/frameworks/native/rdb/mock/include/rdb_store_impl.h +++ b/relational_store/frameworks/native/rdb/mock/include/rdb_store_impl.h @@ -26,7 +26,6 @@ #include "rdb_store_config.h" #include "sqlite_connection_pool.h" #include "sqlite_statement.h" -#include "store_session.h" #include "transaction_observer.h" namespace OHOS::NativeRdb { @@ -104,8 +103,6 @@ private: SqliteConnectionPool *connectionPool; static const int MAX_IDLE_SESSION_SIZE = 5; std::mutex sessionMutex; - std::map, int>> threadMap; - std::list> idleSessions; bool isOpen; std::string path; std::string orgPath; diff --git a/relational_store/frameworks/native/rdb/mock/include/sqlite_connection.h b/relational_store/frameworks/native/rdb/mock/include/sqlite_connection.h index 1526f867..c87cb0ab 100644 --- a/relational_store/frameworks/native/rdb/mock/include/sqlite_connection.h +++ b/relational_store/frameworks/native/rdb/mock/include/sqlite_connection.h @@ -60,7 +60,7 @@ private: int Config(const SqliteConfig &config); int SetPageSize(const SqliteConfig &config); int SetEncryptAlgo(const SqliteConfig &config); - int SetEncryptKey(const std::vector &encryptKey); + int SetEncryptKey(const SqliteConfig &config); int SetJournalMode(const SqliteConfig &config); int SetJournalSizeLimit(const SqliteConfig &config); int SetAutoCheckpoint(const SqliteConfig &config); diff --git a/relational_store/frameworks/native/rdb/mock/include/sqlite_connection_pool.h b/relational_store/frameworks/native/rdb/mock/include/sqlite_connection_pool.h index 7d02e684..73101e55 100644 --- a/relational_store/frameworks/native/rdb/mock/include/sqlite_connection_pool.h +++ b/relational_store/frameworks/native/rdb/mock/include/sqlite_connection_pool.h @@ -44,7 +44,7 @@ public: int ChangeDbFileForRestore(const std::string newPath, const std::string backupPath, const std::vector &newKey); std::stack &getTransactionStack(); - void AcquireTransaction(); + int AcquireTransaction(); void ReleaseTransaction(); private: diff --git a/relational_store/frameworks/native/rdb/mock/include/sqlite_utils.h b/relational_store/frameworks/native/rdb/mock/include/sqlite_utils.h index c6d5afba..577a7f08 100644 --- a/relational_store/frameworks/native/rdb/mock/include/sqlite_utils.h +++ b/relational_store/frameworks/native/rdb/mock/include/sqlite_utils.h @@ -42,6 +42,7 @@ public: static std::string StrToUpper(std::string s); static bool DeleteFile(const std::string path); static int RenameFile(const std::string srcFile, const std::string destFile); + static std::string Anonymous(const std::string &srcFile); static int GetFileSize(const std::string fileName); private: diff --git a/relational_store/frameworks/native/rdb/mock/include/step_result_set.h b/relational_store/frameworks/native/rdb/mock/include/step_result_set.h index 209669bc..85d52516 100644 --- a/relational_store/frameworks/native/rdb/mock/include/step_result_set.h +++ b/relational_store/frameworks/native/rdb/mock/include/step_result_set.h @@ -54,7 +54,6 @@ public: int PrepareStep(); private: - int CheckSession(); void Reset(); std::shared_ptr rdb; std::string sql; diff --git a/relational_store/frameworks/native/rdb/src/abs_predicates.cpp b/relational_store/frameworks/native/rdb/src/abs_predicates.cpp index 982174cb..cf34ed33 100644 --- a/relational_store/frameworks/native/rdb/src/abs_predicates.cpp +++ b/relational_store/frameworks/native/rdb/src/abs_predicates.cpp @@ -98,8 +98,7 @@ AbsPredicates *AbsPredicates::BeginWrap() AbsPredicates *AbsPredicates::EndWrap() { if (!isNeedAnd) { - LOG_WARN("AbsPredicates.endGroup(): you cannot use function or() before end parenthesis,\ - start a AbsPredicates with endGroup(), or use endGroup() right after beginGroup()."); + LOG_WARN("fail to add EndWrap."); return this; } whereClause += " ) "; @@ -109,8 +108,7 @@ AbsPredicates *AbsPredicates::EndWrap() AbsPredicates *AbsPredicates::Or() { if (!isNeedAnd) { - LOG_WARN("QueryImpl.or(): you are starting a sql request with predicate \"or\" or \ - using function or() immediately after another or(). that is ridiculous."); + LOG_WARN("fail to add Or."); return this; } whereClause += " OR "; @@ -121,7 +119,7 @@ AbsPredicates *AbsPredicates::Or() AbsPredicates *AbsPredicates::And() { if (!isNeedAnd) { - LOG_WARN("QueryImpl.and(): you should not start a request with \"and\" or use or() before this function."); + LOG_WARN("fail to add And."); return this; } return this; diff --git a/relational_store/frameworks/native/rdb/src/abs_result_set.cpp b/relational_store/frameworks/native/rdb/src/abs_result_set.cpp index c4c0348b..b7c7fc1a 100644 --- a/relational_store/frameworks/native/rdb/src/abs_result_set.cpp +++ b/relational_store/frameworks/native/rdb/src/abs_result_set.cpp @@ -91,7 +91,7 @@ int AbsResultSet::GoTo(int offset) DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__)); int ret = GoToRow(rowPos_ + offset); if (ret != E_OK) { - LOG_WARN("AbsResultSet::GoTo return ret is wrong!"); + LOG_WARN("GoToRow ret is %{public}d", ret); return ret; } return E_OK; @@ -102,7 +102,7 @@ int AbsResultSet::GoToFirstRow() DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__)); int ret = GoToRow(0); if (ret != E_OK) { - LOG_WARN("AbsResultSet::GoToFirstRow return ret is wrong!"); + LOG_WARN("GoToRow ret is %{public}d", ret); return ret; } return E_OK; @@ -114,13 +114,13 @@ int AbsResultSet::GoToLastRow() int rowCnt = 0; int ret = GetRowCount(rowCnt); if (ret != E_OK) { - LOG_WARN("AbsResultSet::GoToLastRow return GetRowCount::ret is wrong!"); + LOG_ERROR("Failed to GetRowCount, ret is %{public}d", ret); return ret; } ret = GoToRow(rowCnt - 1); if (ret != E_OK) { - LOG_WARN("AbsResultSet::GoToLastRow return GoToRow::ret is wrong!"); + LOG_WARN("GoToRow ret is %{public}d", ret); return ret; } return E_OK; @@ -131,7 +131,7 @@ int AbsResultSet::GoToNextRow() DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__)); int ret = GoToRow(rowPos_ + 1); if (ret != E_OK) { - LOG_WARN("AbsResultSet::GoToNextRow return GoToRow::ret is wrong!"); + LOG_WARN("GoToRow ret is %{public}d", ret); return ret; } return E_OK; @@ -142,7 +142,7 @@ int AbsResultSet::GoToPreviousRow() DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__)); int ret = GoToRow(rowPos_ - 1); if (ret != E_OK) { - LOG_WARN("AbsResultSet::GoToPreviousRow return GoToRow::ret is wrong!"); + LOG_WARN("GoToRow ret is %{public}d", ret); return ret; } return E_OK; @@ -159,7 +159,7 @@ int AbsResultSet::IsAtLastRow(bool &result) int rowCnt = 0; int ret = GetRowCount(rowCnt); if (ret != E_OK) { - LOG_ERROR("AbsResultSet::IsAtLastRow return GetRowCount::ret is wrong!"); + LOG_ERROR("Failed to GetRowCount, ret is %{public}d", ret); return ret; } result = (rowPos_ == (rowCnt - 1)); @@ -175,9 +175,9 @@ int AbsResultSet::IsStarted(bool &result) const int AbsResultSet::IsEnded(bool &result) { int rowCnt = 0; - int ret = GetRowCount(rowCnt); + int ret = GetRowCount(rowCnt); if (ret != E_OK) { - LOG_ERROR("AbsResultSet::IsEnded return GetRowCount::ret is wrong!"); + LOG_ERROR("Failed to GetRowCount, ret is %{public}d", ret); return ret; } result = (rowCnt == 0) ? true : (rowPos_ == rowCnt); @@ -193,7 +193,7 @@ int AbsResultSet::GetColumnCount(int &count) std::vector columnNames; int ret = GetAllColumnNames(columnNames); if (ret != E_OK) { - LOG_ERROR("AbsResultSet::GetColumnCount return GetAllColumnNames::ret is wrong!"); + LOG_ERROR("Failed to GetAllColumnNames, ret is %{public}d", ret); return ret; } columnCount_ = static_cast(columnNames.size()); @@ -218,7 +218,7 @@ int AbsResultSet::GetColumnIndex(const std::string &columnName, int &columnIndex std::vector columnNames; int ret = GetAllColumnNames(columnNames); if (ret != E_OK) { - LOG_ERROR("AbsResultSet::GetColumnIndex return GetAllColumnNames::ret is wrong!"); + LOG_ERROR("Failed to GetAllColumnNames, ret is %{public}d", ret); return ret; } @@ -233,6 +233,7 @@ int AbsResultSet::GetColumnIndex(const std::string &columnName, int &columnIndex columnIndex++; } columnIndex = -1; + LOG_WARN("columnName %{public}s is not in resultSet", columnName.c_str()); return E_ERROR; } @@ -241,10 +242,11 @@ int AbsResultSet::GetColumnName(int columnIndex, std::string &columnName) int rowCnt = 0; int ret = GetColumnCount(rowCnt); if (ret != E_OK) { - LOG_ERROR("AbsResultSet::GetColumnName return GetColumnCount::ret is wrong!"); + LOG_ERROR("Failed to GetColumnCount, ret is %{public}d", ret); return ret; } if (columnIndex >= rowCnt || columnIndex < 0) { + LOG_ERROR("invalid column columnIndex as %{public}d", columnIndex); return E_INVALID_COLUMN_INDEX; } std::vector columnNames; diff --git a/datamgr_service/services/distributeddataservice/framework/cloud/auto_cache.cpp b/relational_store/frameworks/native/rdb/src/asset_value.cpp similarity index 95% rename from datamgr_service/services/distributeddataservice/framework/cloud/auto_cache.cpp rename to relational_store/frameworks/native/rdb/src/asset_value.cpp index c080d640..43ebaa05 100644 --- a/datamgr_service/services/distributeddataservice/framework/cloud/auto_cache.cpp +++ b/relational_store/frameworks/native/rdb/src/asset_value.cpp @@ -13,5 +13,4 @@ * limitations under the License. */ -#include "store_auto_cache.h" - +#include "asset_value.h" diff --git a/relational_store/frameworks/native/rdb/src/rdb_manager.cpp b/relational_store/frameworks/native/rdb/src/rdb_manager.cpp index 76bddfc3..261e420f 100644 --- a/relational_store/frameworks/native/rdb/src/rdb_manager.cpp +++ b/relational_store/frameworks/native/rdb/src/rdb_manager.cpp @@ -17,8 +17,8 @@ #include "rdb_manager_impl.h" namespace OHOS::DistributedRdb { -std::shared_ptr RdbManager::GetRdbService(const RdbSyncerParam& param) +int RdbManager::GetRdbService(const RdbSyncerParam& param, std::shared_ptr &service) { - return RdbManagerImpl::GetInstance().GetRdbService(param); + return RdbManagerImpl::GetInstance().GetRdbService(param, service); } } // namespace OHOS::DistributedRdb diff --git a/relational_store/frameworks/native/rdb/src/rdb_manager_impl.cpp b/relational_store/frameworks/native/rdb/src/rdb_manager_impl.cpp index f7f93488..208c8c21 100644 --- a/relational_store/frameworks/native/rdb/src/rdb_manager_impl.cpp +++ b/relational_store/frameworks/native/rdb/src/rdb_manager_impl.cpp @@ -26,8 +26,10 @@ #include "irdb_service.h" #include "itypes_util.h" #include "rdb_service_proxy.h" +#include "rdb_errno.h" namespace OHOS::DistributedRdb { +using namespace OHOS::NativeRdb; std::shared_ptr RdbManagerImpl::GetDistributedDataManager() { auto manager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); @@ -78,46 +80,40 @@ RdbManagerImpl& RdbManagerImpl::GetInstance() return manager; } -sptr RdbManagerImpl::GetRdbService() +int RdbManagerImpl::GetRdbService(const RdbSyncerParam& param, std::shared_ptr &service) { + std::lock_guard lock(mutex_); + if (rdbService_ != nullptr) { + service = rdbService_; + return E_OK; + } if (distributedDataMgr_ == nullptr) { distributedDataMgr_ = GetDistributedDataManager(); } if (distributedDataMgr_ == nullptr) { ZLOGE("get distributed data manager failed"); - return nullptr; + return E_ERROR; } auto remote = distributedDataMgr_->GetFeatureInterface("relational_store"); if (remote == nullptr) { ZLOGE("get rdb service failed"); - return nullptr; + return E_NOT_SUPPORTED; } - return iface_cast(remote); -} - -std::shared_ptr RdbManagerImpl::GetRdbService(const RdbSyncerParam& param) -{ - std::lock_guard lock(mutex_); - if (rdbService_ != nullptr) { - return rdbService_; - } - auto service = GetRdbService(); - if (service == nullptr) { - return nullptr; - } - if (service->InitNotifier(param) != RDB_OK) { + sptr serviceProxy = iface_cast(remote); + if (serviceProxy->InitNotifier(param) != RDB_OK) { ZLOGE("init notifier failed"); - return nullptr; + return E_ERROR; } - sptr serviceBase = service; + sptr serviceBase = serviceProxy; LinkToDeath(serviceBase->AsObject().GetRefPtr()); - rdbService_ = std::shared_ptr(service.GetRefPtr(), [holder = service] (const auto*) {}); + rdbService_ = std::shared_ptr(serviceProxy.GetRefPtr(), [holder = serviceProxy] (const auto*) {}); if (rdbService_ == nullptr) { - return nullptr; + return E_ERROR; } bundleName_ = param.bundleName_; - return rdbService_; + service = rdbService_; + return E_OK; } void RdbManagerImpl::OnRemoteDied() @@ -134,8 +130,9 @@ void RdbManagerImpl::OnRemoteDied() std::this_thread::sleep_for(std::chrono::seconds(WAIT_TIME)); RdbSyncerParam param; param.bundleName_ = bundleName_; - auto service = GetRdbService(param); - if (service == nullptr) { + std::shared_ptr service = nullptr; + int errCode = GetRdbService(param, service); + if (errCode != E_OK) { return; } proxy = std::static_pointer_cast(service); diff --git a/relational_store/frameworks/native/rdb/src/rdb_security_manager.cpp b/relational_store/frameworks/native/rdb/src/rdb_security_manager.cpp index e060c932..5847fabe 100644 --- a/relational_store/frameworks/native/rdb/src/rdb_security_manager.cpp +++ b/relational_store/frameworks/native/rdb/src/rdb_security_manager.cpp @@ -1,17 +1,17 @@ /* -* 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. -*/ + * 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 "rdb_security_manager.h" @@ -26,6 +26,7 @@ #include "hks_param.h" #include "logger.h" #include "sqlite_database_utils.h" +#include "sqlite_utils.h" namespace OHOS { namespace NativeRdb { @@ -33,131 +34,136 @@ RdbPassword::RdbPassword() = default; RdbPassword::~RdbPassword() { - (void)Clear(); + (void)Clear(); } bool RdbPassword::operator==(const RdbPassword &input) const { - if (size_ != input.GetSize()) { - return false; - } - return memcmp(data_, input.GetData(), size_) == 0; + if (size_ != input.GetSize()) { + return false; + } + return memcmp(data_, input.GetData(), size_) == 0; } bool RdbPassword::operator!=(const RdbPassword &input) const { - return !(*this == input); + return !(*this == input); } size_t RdbPassword::GetSize() const { - return size_; + return size_; } const uint8_t *RdbPassword::GetData() const { - return data_; + return data_; } int RdbPassword::SetValue(const uint8_t *inputData, size_t inputSize) { - if (inputSize > MAX_PASSWORD_SIZE) { - return E_ERROR; - } - if (inputSize != 0 && inputData == nullptr) { - return E_ERROR; - } - - if (inputSize != 0) { - std::copy(inputData, inputData + inputSize, data_); - } - - size_t filledSize = std::min(size_, MAX_PASSWORD_SIZE); - if (inputSize < filledSize) { - std::fill(data_ + inputSize, data_ + filledSize, UCHAR_MAX); - } - - size_ = inputSize; - return E_OK; + if (inputSize > MAX_PASSWORD_SIZE) { + return E_ERROR; + } + if (inputSize != 0 && inputData == nullptr) { + return E_ERROR; + } + + if (inputSize != 0) { + std::copy(inputData, inputData + inputSize, data_); + } + + size_t filledSize = std::min(size_, MAX_PASSWORD_SIZE); + if (inputSize < filledSize) { + std::fill(data_ + inputSize, data_ + filledSize, UCHAR_MAX); + } + + size_ = inputSize; + return E_OK; } int RdbPassword::Clear() { - return SetValue(nullptr, 0); + return SetValue(nullptr, 0); +} + +bool RdbPassword::IsValid() const +{ + return size_ != 0; } int32_t RdbSecurityManager::MallocAndCheckBlobData(struct HksBlob *blob, const uint32_t blobSize) { - blob->data = (uint8_t *)malloc(blobSize); - if (blob->data == NULL) { - LOG_ERROR("Blob data is NULL."); - return HKS_FAILURE; - } - return HKS_SUCCESS; + blob->data = (uint8_t *)malloc(blobSize); + if (blob->data == NULL) { + LOG_ERROR("Blob data is NULL."); + return HKS_FAILURE; + } + return HKS_SUCCESS; } int32_t RdbSecurityManager::HksLoopUpdate(const struct HksBlob *handle, const struct HksParamSet *paramSet, - const struct HksBlob *inData, struct HksBlob *outData) -{ - struct HksBlob inDataSeg = *inData; - uint8_t *lastPtr = inData->data + inData->size - 1; - uint8_t *cur = outData->data; - uint32_t length = outData->size; - outData->size = 0; - - inDataSeg.size = MAX_UPDATE_SIZE; - while (inDataSeg.data <= lastPtr) { - if (inDataSeg.data + MAX_UPDATE_SIZE > lastPtr) { - inDataSeg.size = lastPtr - inDataSeg.data + 1; - break; - } - struct HksBlob outDataSeg = { length - outData->size, cur }; - if (HksUpdate(handle, paramSet, &inDataSeg, &outDataSeg) != HKS_SUCCESS) { - LOG_ERROR("HksUpdate Failed."); - return HKS_FAILURE; - } - cur += outDataSeg.size; - outData->size += outDataSeg.size; - if (inDataSeg.data + MAX_UPDATE_SIZE > lastPtr) { - LOG_ERROR("isFinished and inDataSeg data Error"); - return HKS_FAILURE; - } - inDataSeg.data += MAX_UPDATE_SIZE; - } - - struct HksBlob outDataFinish = { length - outData->size, cur }; - if (HksFinish(handle, paramSet, &inDataSeg, &outDataFinish) != HKS_SUCCESS) { - LOG_ERROR("HksFinish Failed."); - return HKS_FAILURE; - } - outData->size += outDataFinish.size; - return HKS_SUCCESS; + const struct HksBlob *inData, struct HksBlob *outData) +{ + struct HksBlob inDataSeg = *inData; + uint8_t *lastPtr = inData->data + inData->size - 1; + uint8_t *cur = outData->data; + uint32_t length = outData->size; + outData->size = 0; + + inDataSeg.size = MAX_UPDATE_SIZE; + while (inDataSeg.data <= lastPtr) { + if (inDataSeg.data + MAX_UPDATE_SIZE > lastPtr) { + inDataSeg.size = lastPtr - inDataSeg.data + 1; + break; + } + struct HksBlob outDataSeg = { length - outData->size, cur }; + if (HksUpdate(handle, paramSet, &inDataSeg, &outDataSeg) != HKS_SUCCESS) { + LOG_ERROR("HksUpdate Failed."); + return HKS_FAILURE; + } + cur += outDataSeg.size; + outData->size += outDataSeg.size; + if (inDataSeg.data + MAX_UPDATE_SIZE > lastPtr) { + LOG_ERROR("isFinished and inDataSeg data Error"); + return HKS_FAILURE; + } + inDataSeg.data += MAX_UPDATE_SIZE; + } + + struct HksBlob outDataFinish = { length - outData->size, cur }; + if (HksFinish(handle, paramSet, &inDataSeg, &outDataFinish) != HKS_SUCCESS) { + LOG_ERROR("HksFinish Failed."); + return HKS_FAILURE; + } + outData->size += outDataFinish.size; + return HKS_SUCCESS; } int32_t RdbSecurityManager::HksEncryptThreeStage(const struct HksBlob *keyAlias, const struct HksParamSet *paramSet, - const struct HksBlob *plainText, struct HksBlob *cipherText) + const struct HksBlob *plainText, struct HksBlob *cipherText) { - uint8_t handle[sizeof(uint64_t)] = { 0 }; - struct HksBlob handleBlob = { sizeof(uint64_t), handle }; - int32_t result = HksInit(keyAlias, paramSet, &handleBlob, nullptr); - if (result != HKS_SUCCESS) { - LOG_ERROR("HksEncrypt failed with error %{public}d", result); - return result; - } - return HksLoopUpdate(&handleBlob, paramSet, plainText, cipherText); + uint8_t handle[sizeof(uint64_t)] = { 0 }; + struct HksBlob handleBlob = { sizeof(uint64_t), handle }; + int32_t result = HksInit(keyAlias, paramSet, &handleBlob, nullptr); + if (result != HKS_SUCCESS) { + LOG_ERROR("HksEncrypt failed with error %{public}d", result); + return result; + } + return HksLoopUpdate(&handleBlob, paramSet, plainText, cipherText); } int32_t RdbSecurityManager::HksDecryptThreeStage(const struct HksBlob *keyAlias, const struct HksParamSet *paramSet, - const struct HksBlob *cipherText, struct HksBlob *plainText) + const struct HksBlob *cipherText, struct HksBlob *plainText) { - uint8_t handle[sizeof(uint64_t)] = { 0 }; - struct HksBlob handleBlob = { sizeof(uint64_t), handle }; - int32_t result = HksInit(keyAlias, paramSet, &handleBlob, nullptr); - if (result != HKS_SUCCESS) { - LOG_ERROR("HksEncrypt failed with error %{public}d", result); - return result; - } - return HksLoopUpdate(&handleBlob, paramSet, cipherText, plainText); + uint8_t handle[sizeof(uint64_t)] = { 0 }; + struct HksBlob handleBlob = { sizeof(uint64_t), handle }; + int32_t result = HksInit(keyAlias, paramSet, &handleBlob, nullptr); + if (result != HKS_SUCCESS) { + LOG_ERROR("HksEncrypt failed with error %{public}d", result); + return result; + } + return HksLoopUpdate(&handleBlob, paramSet, cipherText, plainText); } RdbSecurityManager::RdbSecurityManager() = default; @@ -166,449 +172,483 @@ RdbSecurityManager::~RdbSecurityManager() = default; std::vector RdbSecurityManager::GenerateRandomNum(int32_t len) { - std::random_device randomDevice; - std::uniform_int_distribution distribution(0, std::numeric_limits::max()); - std::vector key(len); - for (int32_t i = 0; i < len; i++) { - key[i] = static_cast(distribution(randomDevice)); - } - return key; + std::random_device randomDevice; + std::uniform_int_distribution distribution(0, std::numeric_limits::max()); + std::vector key(len); + for (int32_t i = 0; i < len; i++) { + key[i] = static_cast(distribution(randomDevice)); + } + return key; } -bool RdbSecurityManager::SaveSecretKeyToFile(RdbSecurityManager::KeyFileType keyFile, const std::vector &key) +bool RdbSecurityManager::SaveSecretKeyToFile(RdbSecurityManager::KeyFileType keyFile) { - LOG_INFO("SaveSecretKeyToFile begin."); - if (!CheckRootKeyExists()) { - LOG_ERROR("Root key not exists!"); - return false; - } - RdbSecretKeyData keyData; - keyData.timeValue = std::chrono::system_clock::to_time_t(std::chrono::system_clock::system_clock::now()); - keyData.distributed = 0; - keyData.secretKey = EncryptWorkKey(key); - - if (keyData.secretKey.size() == 0) { - return false; - } - - if (!RdbSecurityManager::InitPath(dbKeyDir_)) { - return false; - } - - std::string keyPath; - if (keyFile == KeyFileType::PUB_KEY_FILE) { - keyPath = keyPath_; - } else { - keyPath = keyBakPath_; - } - - return SaveSecretKeyToDisk(keyPath, keyData); + LOG_INFO("SaveSecretKeyToFile begin."); + if (!CheckRootKeyExists()) { + LOG_ERROR("Root key not exists!"); + return false; + } + std::vector key = GenerateRandomNum(RDB_KEY_SIZE); + RdbSecretKeyData keyData; + keyData.timeValue = std::chrono::system_clock::to_time_t(std::chrono::system_clock::system_clock::now()); + keyData.distributed = 0; + keyData.secretKey = EncryptWorkKey(key); + + if (keyData.secretKey.empty()) { + LOG_ERROR("Key size is 0"); + key.assign(key.size(), 0); + return false; + } + + key.assign(key.size(), 0); + if (!RdbSecurityManager::InitPath(dbKeyDir_)) { + LOG_ERROR("InitPath err."); + return false; + } + + std::string keyPath; + GetKeyPath(keyFile, keyPath); + + return SaveSecretKeyToDisk(keyPath, keyData); } bool RdbSecurityManager::SaveSecretKeyToDisk(const std::string &path, RdbSecretKeyData &keyData) { - LOG_INFO("SaveSecretKeyToDisk begin."); - std::lock_guard lock(mutex_); - std::vector key; - key.push_back(keyData.distributed); - key.insert(key.end(), reinterpret_cast(&keyData.timeValue), reinterpret_cast(&keyData.timeValue) + sizeof(keyData.timeValue)); - key.insert(key.end(), keyData.secretKey.begin(), keyData.secretKey.end()); - - bool ret = SaveBufferToFile(path, key); - if (!ret) { - LOG_ERROR("SaveBufferToFile failed!"); - return false; - } - - return true; + LOG_INFO("SaveSecretKeyToDisk begin."); + std::lock_guard lock(mutex_); + std::vector key; + key.push_back(keyData.distributed); + key.insert(key.end(), reinterpret_cast(&keyData.timeValue), + reinterpret_cast(&keyData.timeValue) + sizeof(keyData.timeValue)); + key.insert(key.end(), keyData.secretKey.begin(), keyData.secretKey.end()); + + bool ret = SaveBufferToFile(path, key); + if (!ret) { + LOG_ERROR("SaveBufferToFile failed!"); + return false; + } + + return true; } int RdbSecurityManager::GenerateRootKey() { - LOG_INFO("RDB GenerateRootKey begin."); - struct HksBlob rootKeyName = { uint32_t(rootKeyAlias_.size()), rootKeyAlias_.data() }; - struct HksParamSet *params = nullptr; - int32_t ret = HksInitParamSet(¶ms); - if (ret != HKS_SUCCESS) { - LOG_ERROR("HksInitParamSet()-client failed with error %{public}d", ret); - return ret; - } - - struct HksParam hksParam[] = { - { .tag = HKS_TAG_ALGORITHM, .uint32Param = HKS_ALG_AES }, - { .tag = HKS_TAG_KEY_SIZE, .uint32Param = HKS_AES_KEY_SIZE_256 }, - { .tag = HKS_TAG_PURPOSE, .uint32Param = HKS_KEY_PURPOSE_ENCRYPT | HKS_KEY_PURPOSE_DECRYPT }, - { .tag = HKS_TAG_DIGEST, .uint32Param = 0 }, - { .tag = HKS_TAG_PADDING, .uint32Param = HKS_PADDING_NONE }, - { .tag = HKS_TAG_BLOCK_MODE, .uint32Param = HKS_MODE_GCM }, - }; - - ret = HksAddParams(params, hksParam, sizeof(hksParam) / sizeof(hksParam[0])); - if (ret != HKS_SUCCESS) { - LOG_ERROR("HksAddParams-client failed with error %{public}d", ret); - HksFreeParamSet(¶ms); - return ret; - } - - ret = HksBuildParamSet(¶ms); - if (ret != HKS_SUCCESS) { - LOG_ERROR("HksBuildParamSet-client failed with error %{public}d", ret); - HksFreeParamSet(¶ms); - return ret; - } - - ret = HksGenerateKey(&rootKeyName, params, nullptr); - HksFreeParamSet(¶ms); - if (ret != HKS_SUCCESS) { - LOG_ERROR("HksGenerateKey-client failed with error %{public}d", ret); - } - LOG_INFO("RDB root key generated successful."); - return ret; + LOG_INFO("RDB GenerateRootKey begin."); + struct HksBlob rootKeyName = { uint32_t(rootKeyAlias_.size()), rootKeyAlias_.data() }; + struct HksParamSet *params = nullptr; + int32_t ret = HksInitParamSet(¶ms); + if (ret != HKS_SUCCESS) { + LOG_ERROR("HksInitParamSet()-client failed with error %{public}d", ret); + return ret; + } + + struct HksParam hksParam[] = { + { .tag = HKS_TAG_ALGORITHM, .uint32Param = HKS_ALG_AES }, + { .tag = HKS_TAG_KEY_SIZE, .uint32Param = HKS_AES_KEY_SIZE_256 }, + { .tag = HKS_TAG_PURPOSE, .uint32Param = HKS_KEY_PURPOSE_ENCRYPT | HKS_KEY_PURPOSE_DECRYPT }, + { .tag = HKS_TAG_DIGEST, .uint32Param = 0 }, + { .tag = HKS_TAG_PADDING, .uint32Param = HKS_PADDING_NONE }, + { .tag = HKS_TAG_BLOCK_MODE, .uint32Param = HKS_MODE_GCM }, + }; + + ret = HksAddParams(params, hksParam, sizeof(hksParam) / sizeof(hksParam[0])); + if (ret != HKS_SUCCESS) { + LOG_ERROR("HksAddParams-client failed with error %{public}d", ret); + HksFreeParamSet(¶ms); + return ret; + } + + ret = HksBuildParamSet(¶ms); + if (ret != HKS_SUCCESS) { + LOG_ERROR("HksBuildParamSet-client failed with error %{public}d", ret); + HksFreeParamSet(¶ms); + return ret; + } + + ret = HksGenerateKey(&rootKeyName, params, nullptr); + HksFreeParamSet(¶ms); + if (ret != HKS_SUCCESS) { + LOG_ERROR("HksGenerateKey-client failed with error %{public}d", ret); + } + LOG_INFO("RDB root key generated successful."); + return ret; } std::vector RdbSecurityManager::EncryptWorkKey(const std::vector &key) { - struct HksBlob blobAad = { uint32_t(aad_.size()), aad_.data() }; - struct HksBlob blobNonce = { uint32_t(nonce_.size()), nonce_.data() }; - struct HksBlob rootKeyName = { uint32_t(rootKeyAlias_.size()), rootKeyAlias_.data() }; - struct HksBlob plainKey = { uint32_t(key.size()), const_cast(key.data()) }; - struct HksParamSet *params = nullptr; - int32_t ret = HksInitParamSet(¶ms); - if (ret != HKS_SUCCESS) { - LOG_ERROR("HksInitParamSet() failed with error %{public}d", ret); - return {}; - } - struct HksParam hksParam[] = { - { .tag = HKS_TAG_ALGORITHM, .uint32Param = HKS_ALG_AES }, - { .tag = HKS_TAG_PURPOSE, .uint32Param = HKS_KEY_PURPOSE_ENCRYPT }, - { .tag = HKS_TAG_DIGEST, .uint32Param = 0 }, - { .tag = HKS_TAG_BLOCK_MODE, .uint32Param = HKS_MODE_GCM }, - { .tag = HKS_TAG_PADDING, .uint32Param = HKS_PADDING_NONE }, - { .tag = HKS_TAG_NONCE, .blob = blobNonce }, - { .tag = HKS_TAG_ASSOCIATED_DATA, .blob = blobAad }, - }; - ret = HksAddParams(params, hksParam, sizeof(hksParam) / sizeof(hksParam[0])); - if (ret != HKS_SUCCESS) { - LOG_ERROR("HksAddParams failed with error %{public}d", ret); - HksFreeParamSet(¶ms); - return {}; - } - - ret = HksBuildParamSet(¶ms); - if (ret != HKS_SUCCESS) { - LOG_ERROR("HksBuildParamSet failed with error %{public}d", ret); - HksFreeParamSet(¶ms); - return {}; - } - - uint8_t cipherBuf[256] = { 0 }; - struct HksBlob cipherText = { sizeof(cipherBuf), cipherBuf }; - ret = HksEncryptThreeStage(&rootKeyName, params, &plainKey, &cipherText); - (void)HksFreeParamSet(¶ms); - if (ret != HKS_SUCCESS) { - (void)memset_s(cipherBuf, sizeof(cipherBuf), 0, sizeof(cipherBuf)); - LOG_ERROR("HksEncrypt failed with error %{public}d", ret); - return {}; - } - - std::vector encryptedKey(cipherText.data, cipherText.data + cipherText.size); - (void)memset_s(cipherBuf, sizeof(cipherBuf), 0, sizeof(cipherBuf)); - - return encryptedKey; + struct HksBlob blobAad = { uint32_t(aad_.size()), aad_.data() }; + struct HksBlob blobNonce = { uint32_t(nonce_.size()), nonce_.data() }; + struct HksBlob rootKeyName = { uint32_t(rootKeyAlias_.size()), rootKeyAlias_.data() }; + struct HksBlob plainKey = { uint32_t(key.size()), const_cast(key.data()) }; + struct HksParamSet *params = nullptr; + int32_t ret = HksInitParamSet(¶ms); + if (ret != HKS_SUCCESS) { + LOG_ERROR("HksInitParamSet() failed with error %{public}d", ret); + return {}; + } + struct HksParam hksParam[] = { + { .tag = HKS_TAG_ALGORITHM, .uint32Param = HKS_ALG_AES }, + { .tag = HKS_TAG_PURPOSE, .uint32Param = HKS_KEY_PURPOSE_ENCRYPT }, + { .tag = HKS_TAG_DIGEST, .uint32Param = 0 }, + { .tag = HKS_TAG_BLOCK_MODE, .uint32Param = HKS_MODE_GCM }, + { .tag = HKS_TAG_PADDING, .uint32Param = HKS_PADDING_NONE }, + { .tag = HKS_TAG_NONCE, .blob = blobNonce }, + { .tag = HKS_TAG_ASSOCIATED_DATA, .blob = blobAad }, + }; + ret = HksAddParams(params, hksParam, sizeof(hksParam) / sizeof(hksParam[0])); + if (ret != HKS_SUCCESS) { + LOG_ERROR("HksAddParams failed with error %{public}d", ret); + HksFreeParamSet(¶ms); + return {}; + } + + ret = HksBuildParamSet(¶ms); + if (ret != HKS_SUCCESS) { + LOG_ERROR("HksBuildParamSet failed with error %{public}d", ret); + HksFreeParamSet(¶ms); + return {}; + } + + uint8_t cipherBuf[256] = { 0 }; + struct HksBlob cipherText = { sizeof(cipherBuf), cipherBuf }; + ret = HksEncryptThreeStage(&rootKeyName, params, &plainKey, &cipherText); + (void)HksFreeParamSet(¶ms); + if (ret != HKS_SUCCESS) { + (void)memset_s(cipherBuf, sizeof(cipherBuf), 0, sizeof(cipherBuf)); + LOG_ERROR("HksEncrypt failed with error %{public}d", ret); + return {}; + } + + std::vector encryptedKey(cipherText.data, cipherText.data + cipherText.size); + (void)memset_s(cipherBuf, sizeof(cipherBuf), 0, sizeof(cipherBuf)); + + return encryptedKey; } bool RdbSecurityManager::DecryptWorkKey(std::vector &source, std::vector &key) { - uint8_t aead_[AEAD_LEN] = { 0 }; - struct HksBlob blobAad = { uint32_t(aad_.size()), &(aad_[0]) }; - struct HksBlob blobNonce = { uint32_t(nonce_.size()), &(nonce_[0]) }; - struct HksBlob rootKeyName = { uint32_t(rootKeyAlias_.size()), &(rootKeyAlias_[0]) }; - struct HksBlob encryptedKeyBlob = { uint32_t(source.size() - AEAD_LEN), source.data() }; - struct HksBlob blobAead = { AEAD_LEN, aead_ }; - if (memcpy_s(aead_, AEAD_LEN, source.data() + source.size() - AEAD_LEN, AEAD_LEN) != 0) { - return false; - } - - struct HksParamSet *params = nullptr; - int32_t ret = HksInitParamSet(¶ms); - if (ret != HKS_SUCCESS) { - LOG_ERROR("HksInitParamSet() failed with error %{public}d", ret); - return false; - } - struct HksParam hksParam[] = { - { .tag = HKS_TAG_ALGORITHM, .uint32Param = HKS_ALG_AES }, - { .tag = HKS_TAG_PURPOSE, .uint32Param = HKS_KEY_PURPOSE_DECRYPT }, - { .tag = HKS_TAG_DIGEST, .uint32Param = 0 }, - { .tag = HKS_TAG_BLOCK_MODE, .uint32Param = HKS_MODE_GCM }, - { .tag = HKS_TAG_PADDING, .uint32Param = HKS_PADDING_NONE }, - { .tag = HKS_TAG_NONCE, .blob = blobNonce }, - { .tag = HKS_TAG_ASSOCIATED_DATA, .blob = blobAad }, - { .tag = HKS_TAG_AE_TAG, .blob = blobAead }, - }; - ret = HksAddParams(params, hksParam, sizeof(hksParam) / sizeof(hksParam[0])); - if (ret != HKS_SUCCESS) { - LOG_ERROR("HksAddParams failed with error %{public}d", ret); - HksFreeParamSet(¶ms); - return false; - } - - ret = HksBuildParamSet(¶ms); - if (ret != HKS_SUCCESS) { - LOG_ERROR("HksBuildParamSet failed with error %{public}d", ret); - HksFreeParamSet(¶ms); - return false; - } - - uint8_t plainBuf[512] = { 0 }; - struct HksBlob plainKeyBlob = { sizeof(plainBuf), plainBuf }; - ret = HksDecryptThreeStage(&rootKeyName, params, &encryptedKeyBlob, &plainKeyBlob); - (void)HksFreeParamSet(¶ms); - if (ret != HKS_SUCCESS) { - (void)memset_s(plainBuf, sizeof(plainBuf), 0, sizeof(plainBuf)); - LOG_ERROR("HksDecrypt failed with error %{public}d", ret); - return false; - } - - key.assign(plainKeyBlob.data, plainKeyBlob.data + plainKeyBlob.size); - (void)memset_s(plainBuf, sizeof(plainBuf), 0, sizeof(plainBuf)); - return true; + uint8_t aead_[AEAD_LEN] = { 0 }; + struct HksBlob blobAad = { uint32_t(aad_.size()), &(aad_[0]) }; + struct HksBlob blobNonce = { uint32_t(nonce_.size()), &(nonce_[0]) }; + struct HksBlob rootKeyName = { uint32_t(rootKeyAlias_.size()), &(rootKeyAlias_[0]) }; + struct HksBlob encryptedKeyBlob = { uint32_t(source.size() - AEAD_LEN), source.data() }; + struct HksBlob blobAead = { AEAD_LEN, aead_ }; + if (memcpy_s(aead_, AEAD_LEN, source.data() + source.size() - AEAD_LEN, AEAD_LEN) != 0) { + return false; + } + + struct HksParamSet *params = nullptr; + int32_t ret = HksInitParamSet(¶ms); + if (ret != HKS_SUCCESS) { + LOG_ERROR("HksInitParamSet() failed with error %{public}d", ret); + return false; + } + struct HksParam hksParam[] = { + { .tag = HKS_TAG_ALGORITHM, .uint32Param = HKS_ALG_AES }, + { .tag = HKS_TAG_PURPOSE, .uint32Param = HKS_KEY_PURPOSE_DECRYPT }, + { .tag = HKS_TAG_DIGEST, .uint32Param = 0 }, + { .tag = HKS_TAG_BLOCK_MODE, .uint32Param = HKS_MODE_GCM }, + { .tag = HKS_TAG_PADDING, .uint32Param = HKS_PADDING_NONE }, + { .tag = HKS_TAG_NONCE, .blob = blobNonce }, + { .tag = HKS_TAG_ASSOCIATED_DATA, .blob = blobAad }, + { .tag = HKS_TAG_AE_TAG, .blob = blobAead }, + }; + ret = HksAddParams(params, hksParam, sizeof(hksParam) / sizeof(hksParam[0])); + if (ret != HKS_SUCCESS) { + LOG_ERROR("HksAddParams failed with error %{public}d", ret); + HksFreeParamSet(¶ms); + return false; + } + + ret = HksBuildParamSet(¶ms); + if (ret != HKS_SUCCESS) { + LOG_ERROR("HksBuildParamSet failed with error %{public}d", ret); + HksFreeParamSet(¶ms); + return false; + } + + uint8_t plainBuf[512] = { 0 }; + struct HksBlob plainKeyBlob = { sizeof(plainBuf), plainBuf }; + ret = HksDecryptThreeStage(&rootKeyName, params, &encryptedKeyBlob, &plainKeyBlob); + (void)HksFreeParamSet(¶ms); + if (ret != HKS_SUCCESS) { + (void)memset_s(plainBuf, sizeof(plainBuf), 0, sizeof(plainBuf)); + LOG_ERROR("HksDecrypt failed with error %{public}d", ret); + return false; + } + + key.assign(plainKeyBlob.data, plainKeyBlob.data + plainKeyBlob.size); + (void)memset_s(plainBuf, sizeof(plainBuf), 0, sizeof(plainBuf)); + return true; } void RdbSecurityManager::Init(const std::string &bundleName, const std::string &path) { - rootKeyAlias_ = GenerateRootKeyAlias(bundleName); - nonce_ = std::vector(RDB_HKS_BLOB_TYPE_NONCE, RDB_HKS_BLOB_TYPE_NONCE + strlen(RDB_HKS_BLOB_TYPE_NONCE)); - aad_ = std::vector(RDB_HKS_BLOB_TYPE_AAD, RDB_HKS_BLOB_TYPE_AAD + strlen(RDB_HKS_BLOB_TYPE_AAD)); - - ParsePath(path); - if (CheckRootKeyExists()) { - return; - } - constexpr uint32_t RETRY_MAX_TIMES = 5; - uint32_t retryCount = 0; - constexpr int RETRY_TIME_INTERVAL_MILLISECOND = 1 * 1000 * 1000; - while (retryCount < RETRY_MAX_TIMES) { - auto ret = GenerateRootKey(); - if (ret == HKS_SUCCESS) { - break; - } - retryCount++; - LOG_ERROR("RDB generate root key failed, try count:%{public}u", retryCount); - usleep(RETRY_TIME_INTERVAL_MILLISECOND); - } + rootKeyAlias_ = GenerateRootKeyAlias(bundleName); + nonce_ = std::vector(RDB_HKS_BLOB_TYPE_NONCE, RDB_HKS_BLOB_TYPE_NONCE + strlen(RDB_HKS_BLOB_TYPE_NONCE)); + aad_ = std::vector(RDB_HKS_BLOB_TYPE_AAD, RDB_HKS_BLOB_TYPE_AAD + strlen(RDB_HKS_BLOB_TYPE_AAD)); + + ParsePath(path); + if (CheckRootKeyExists()) { + return; + } + constexpr uint32_t RETRY_MAX_TIMES = 5; + uint32_t retryCount = 0; + constexpr int RETRY_TIME_INTERVAL_MILLISECOND = 1 * 1000 * 1000; + while (retryCount < RETRY_MAX_TIMES) { + auto ret = GenerateRootKey(); + if (ret == HKS_SUCCESS) { + break; + } + retryCount++; + LOG_ERROR("RDB generate root key failed, try count:%{public}u", retryCount); + usleep(RETRY_TIME_INTERVAL_MILLISECOND); + } } bool RdbSecurityManager::CheckRootKeyExists() { - LOG_INFO("RDB checkRootKeyExist begin."); - struct HksBlob rootKeyName = { uint32_t(rootKeyAlias_.size()), rootKeyAlias_.data() }; - struct HksParamSet *params = nullptr; - int32_t ret = HksInitParamSet(¶ms); - if (ret != HKS_SUCCESS) { - LOG_ERROR("HksInitParamSet()-client failed with error %{public}d", ret); - return ret; - } - - struct HksParam hksParam[] = { - { .tag = HKS_TAG_ALGORITHM, .uint32Param = HKS_ALG_AES }, - { .tag = HKS_TAG_KEY_SIZE, .uint32Param = HKS_AES_KEY_SIZE_256 }, - { .tag = HKS_TAG_PURPOSE, .uint32Param = HKS_KEY_PURPOSE_ENCRYPT | HKS_KEY_PURPOSE_DECRYPT }, - { .tag = HKS_TAG_DIGEST, .uint32Param = 0 }, - { .tag = HKS_TAG_PADDING, .uint32Param = HKS_PADDING_NONE }, - { .tag = HKS_TAG_BLOCK_MODE, .uint32Param = HKS_MODE_GCM }, - }; - - ret = HksAddParams(params, hksParam, sizeof(hksParam) / sizeof(hksParam[0])); - if (ret != HKS_SUCCESS) { - LOG_ERROR("HksAddParams failed with error %{public}d", ret); - HksFreeParamSet(¶ms); - return ret; - } - - ret = HksBuildParamSet(¶ms); - if (ret != HKS_SUCCESS) { - LOG_ERROR("HksBuildParamSet failed with error %{public}d", ret); - HksFreeParamSet(¶ms); - return ret; - } - - ret = HksKeyExist(&rootKeyName, params); - HksFreeParamSet(¶ms); - if (ret != HKS_SUCCESS) { - LOG_ERROR("HksEncrypt failed with error %{public}d", ret); - } - return ret == HKS_SUCCESS; + LOG_INFO("RDB checkRootKeyExist begin."); + struct HksBlob rootKeyName = { uint32_t(rootKeyAlias_.size()), rootKeyAlias_.data() }; + struct HksParamSet *params = nullptr; + int32_t ret = HksInitParamSet(¶ms); + if (ret != HKS_SUCCESS) { + LOG_ERROR("HksInitParamSet()-client failed with error %{public}d", ret); + return ret; + } + + struct HksParam hksParam[] = { + { .tag = HKS_TAG_ALGORITHM, .uint32Param = HKS_ALG_AES }, + { .tag = HKS_TAG_KEY_SIZE, .uint32Param = HKS_AES_KEY_SIZE_256 }, + { .tag = HKS_TAG_PURPOSE, .uint32Param = HKS_KEY_PURPOSE_ENCRYPT | HKS_KEY_PURPOSE_DECRYPT }, + { .tag = HKS_TAG_DIGEST, .uint32Param = 0 }, + { .tag = HKS_TAG_PADDING, .uint32Param = HKS_PADDING_NONE }, + { .tag = HKS_TAG_BLOCK_MODE, .uint32Param = HKS_MODE_GCM }, + }; + + ret = HksAddParams(params, hksParam, sizeof(hksParam) / sizeof(hksParam[0])); + if (ret != HKS_SUCCESS) { + LOG_ERROR("HksAddParams failed with error %{public}d", ret); + HksFreeParamSet(¶ms); + return ret; + } + + ret = HksBuildParamSet(¶ms); + if (ret != HKS_SUCCESS) { + LOG_ERROR("HksBuildParamSet failed with error %{public}d", ret); + HksFreeParamSet(¶ms); + return ret; + } + + ret = HksKeyExist(&rootKeyName, params); + HksFreeParamSet(¶ms); + if (ret != HKS_SUCCESS) { + LOG_ERROR("HksEncrypt failed with error %{public}d", ret); + } + return ret == HKS_SUCCESS; } bool RdbSecurityManager::InitPath(const std::string &path) { - constexpr mode_t DEFAULT_UMASK = 0002; - if (access(path.c_str(), F_OK) == 0) { - return true; - } - umask(DEFAULT_UMASK); - if (mkdir(path.c_str(), (S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)) != 0 && errno != EEXIST) { - LOG_ERROR("mkdir error:%{public}d, dbDir:%{public}s", errno, path.c_str()); - return false; - } - return true; + constexpr mode_t DEFAULT_UMASK = 0002; + if (access(path.c_str(), F_OK) == 0) { + return true; + } + umask(DEFAULT_UMASK); + if (mkdir(path.c_str(), (S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)) != 0 && errno != EEXIST) { + LOG_ERROR("mkdir error:%{public}d, dbDir:%{public}s", errno, SqliteUtils::Anonymous(path).c_str()); + return false; + } + return true; } -bool RdbSecurityManager::LoadSecretKeyFromDisk(const std::string &keyPath, RdbSecretKeyData &keyData) +RdbPassword RdbSecurityManager::LoadSecretKeyFromFile(KeyFileType keyFile) { - LOG_INFO("LoadSecretKeyFromDisk begin."); - std::vector content; - if (!LoadBufferFromFile(keyPath, content)) { - LOG_ERROR("LoadBufferFromFile failed!"); - return false; - } - - std::vector distribute; - auto iter = content.begin(); - distribute.push_back(*iter); - iter++; - uint8_t distributeStatus = TransferByteArrayToType(distribute); - - std::vector createTime; - for (int i = 0; i < static_cast(sizeof(time_t) / sizeof(uint8_t)); i++) { - createTime.push_back(*iter); - iter++; - } + std::string keyPath; + GetKeyPath(keyFile, keyPath); + if (!FileExists(keyPath)) { + LOG_ERROR("Key file not exists."); + return {}; + } + + RdbSecretKeyData keyData; + if (!LoadSecretKeyFromDisk(keyPath, keyData)) { + LOG_ERROR("Load key failed."); + return {}; + } + + std::vector key; + if (!DecryptWorkKey(keyData.secretKey, key)) { + LOG_ERROR("Decrypt key failed!"); + return {}; + } + + RdbPassword rdbPasswd; + rdbPasswd.isKeyExpired = IsKeyExpired(keyData.timeValue); + rdbPasswd.SetValue(key.data(), key.size()); + key.assign(key.size(), 0); + return rdbPasswd; +} - keyData.distributed = distributeStatus; - keyData.timeValue = TransferByteArrayToType(createTime); - keyData.secretKey.insert(keyData.secretKey.end(), iter, content.end()); - content.assign(content.size(), 0); - return true; +bool RdbSecurityManager::LoadSecretKeyFromDisk(const std::string &keyPath, RdbSecretKeyData &keyData) +{ + LOG_INFO("LoadSecretKeyFromDisk begin."); + std::vector content; + if (!LoadBufferFromFile(keyPath, content)) { + LOG_ERROR("LoadBufferFromFile failed!"); + return false; + } + + std::vector distribute; + auto iter = content.begin(); + distribute.push_back(*iter); + iter++; + uint8_t distributeStatus = TransferByteArrayToType(distribute); + + std::vector createTime; + for (int i = 0; i < static_cast(sizeof(time_t) / sizeof(uint8_t)); i++) { + createTime.push_back(*iter); + iter++; + } + + keyData.distributed = distributeStatus; + keyData.timeValue = TransferByteArrayToType(createTime); + keyData.secretKey.insert(keyData.secretKey.end(), iter, content.end()); + content.assign(content.size(), 0); + return true; } RdbPassword RdbSecurityManager::GetRdbPassword(KeyFileType keyFile) { - LOG_INFO("GetRdbPassword Begin."); - std::string keyPath; - if (keyFile == KeyFileType::PUB_KEY_FILE) { - keyPath = keyPath_; - } else { - keyPath = keyBakPath_; - } - RdbSecretKeyData keyData; - if (!LoadSecretKeyFromDisk(keyPath, keyData)) { - return {}; - } - std::vector key; - if (!DecryptWorkKey(keyData.secretKey, key)) { - LOG_ERROR("GetRdbPassword failed!"); - return {}; - } - - RdbPassword password; - password.SetValue(key.data(), key.size()); - key.assign(key.size(), 0); - return password; + LOG_INFO("GetRdbPassword Begin."); + if (!CheckKeyDataFileExists(keyFile)) { + if (!SaveSecretKeyToFile(keyFile)) { + LOG_ERROR("Failed to save key."); + return {}; + } + } + + return LoadSecretKeyFromFile(keyFile); } std::vector RdbSecurityManager::GenerateRootKeyAlias(const std::string &bundleName) { - bundleName_ = bundleName; - if (bundleName_.empty()) { - LOG_ERROR("BundleName is empty!"); - return {}; - } - std::vector rootKeyAlias = - std::vector(RDB_ROOT_KEY_ALIAS_PREFIX, RDB_ROOT_KEY_ALIAS_PREFIX + strlen(RDB_ROOT_KEY_ALIAS_PREFIX)); - rootKeyAlias.insert(rootKeyAlias.end(), bundleName.begin(), bundleName.end()); - return rootKeyAlias; + bundleName_ = bundleName; + if (bundleName_.empty()) { + LOG_ERROR("BundleName is empty!"); + return {}; + } + std::vector rootKeyAlias = + std::vector(RDB_ROOT_KEY_ALIAS_PREFIX, RDB_ROOT_KEY_ALIAS_PREFIX + strlen(RDB_ROOT_KEY_ALIAS_PREFIX)); + rootKeyAlias.insert(rootKeyAlias.end(), bundleName.begin(), bundleName.end()); + return rootKeyAlias; } void RdbSecurityManager::DelRdbSecretDataFile(const std::string &path) { - LOG_INFO("Delete all key files begin."); - std::lock_guard lock(mutex_); - ParsePath(path); - SqliteDatabaseUtils::DeleteFile(keyPath_); - SqliteDatabaseUtils::DeleteFile(keyBakPath_); + LOG_INFO("Delete all key files begin."); + std::lock_guard lock(mutex_); + ParsePath(path); + SqliteDatabaseUtils::DeleteFile(keyPath_); + SqliteDatabaseUtils::DeleteFile(newKeyPath_); } -bool RdbSecurityManager::IsKeyOutOfdate(const time_t &createTime) const +bool RdbSecurityManager::IsKeyExpired(const time_t &createTime) { - std::chrono::system_clock::time_point createTimeChrono = std::chrono::system_clock::from_time_t(createTime); - return ((createTimeChrono + std::chrono::hours(HOURS_PER_YEAR)) < std::chrono::system_clock::now()); + auto timePoint = std::chrono::system_clock::from_time_t(createTime); + return ((timePoint + std::chrono::hours(HOURS_PER_YEAR)) < std::chrono::system_clock::now()); } RdbSecurityManager &RdbSecurityManager::GetInstance() { - static RdbSecurityManager instance; - return instance; + static RdbSecurityManager instance; + return instance; } static std::string RemoveSuffix(const std::string &name) { - std::string suffix(".db"); - auto pos = name.rfind(suffix); - if (pos == std::string::npos || pos < name.length() - suffix.length()) { - return name; - } - return { name, 0, pos }; + std::string suffix(".db"); + auto pos = name.rfind(suffix); + if (pos == std::string::npos || pos < name.length() - suffix.length()) { + return name; + } + return { name, 0, pos }; } void RdbSecurityManager::ParsePath(const std::string &path) { - dbDir_ = ExtractFilePath(path); - const std::string dbName = ExtractFileName(path); - dbName_ = RemoveSuffix(dbName); - dbKeyDir_ = dbDir_ + std::string("key/"); - keyPath_ = dbKeyDir_ + dbName_ + std::string(RdbSecurityManager::SUFFIX_PUB_KEY); - keyBakPath_ = dbKeyDir_ + dbName_ + std::string(RdbSecurityManager::SUFFIX_PUB_KEY_BAK); + dbDir_ = ExtractFilePath(path); + const std::string dbName = ExtractFileName(path); + dbName_ = RemoveSuffix(dbName); + dbKeyDir_ = dbDir_ + std::string("key/"); + keyPath_ = dbKeyDir_ + dbName_ + std::string(RdbSecurityManager::SUFFIX_PUB_KEY); + newKeyPath_ = dbKeyDir_ + dbName_ + std::string(RdbSecurityManager::SUFFIX_PUB_KEY_NEW); } bool RdbSecurityManager::CheckKeyDataFileExists(RdbSecurityManager::KeyFileType fileType) { - if (fileType == KeyFileType::PUB_KEY_FILE) { - return FileExists(keyPath_); - } else { - return FileExists(keyBakPath_); - } + if (fileType == KeyFileType::PUB_KEY_FILE) { + return FileExists(keyPath_); + } else { + return FileExists(newKeyPath_); + } } int RdbSecurityManager::GetKeyDistributedStatus(KeyFileType keyFile, bool &status) { - LOG_INFO("GetKeyDistributedStatus start."); - std::string keyPath; - if (keyFile == KeyFileType::PUB_KEY_FILE) { - keyPath = keyPath_; - } else { - keyPath = keyBakPath_; - } + LOG_INFO("GetKeyDistributedStatus start."); + std::string keyPath; + GetKeyPath(keyFile, keyPath); - RdbSecretKeyData keyData; - if (!LoadSecretKeyFromDisk(keyPath, keyData)) { - return E_ERROR; - } + RdbSecretKeyData keyData; + if (!LoadSecretKeyFromDisk(keyPath, keyData)) { + return E_ERROR; + } - status = (keyData.distributed == DISTRIBUTED); - return E_OK; + status = (keyData.distributed == DISTRIBUTED); + return E_OK; } int RdbSecurityManager::SetKeyDistributedStatus(KeyFileType keyFile, bool status) { - LOG_INFO("SetKeyDistributedStatus start."); - std::string keyPath; - if (keyFile == KeyFileType::PUB_KEY_FILE) { - keyPath = keyPath_; - } else { - keyPath = keyBakPath_; - } - RdbSecretKeyData keyData; - if (!LoadSecretKeyFromDisk(keyPath, keyData)) { - return E_ERROR; - } - - keyData.distributed = (status ? DISTRIBUTED : UNDISTRIBUTED); - if (!SaveSecretKeyToDisk(keyPath, keyData)) { - return E_ERROR; - } - - return E_OK; + LOG_INFO("SetKeyDistributedStatus start."); + std::string keyPath; + GetKeyPath(keyFile, keyPath); + RdbSecretKeyData keyData; + if (!LoadSecretKeyFromDisk(keyPath, keyData)) { + return E_ERROR; + } + + keyData.distributed = (status ? DISTRIBUTED : UNDISTRIBUTED); + if (!SaveSecretKeyToDisk(keyPath, keyData)) { + return E_ERROR; + } + + return E_OK; +} + +void RdbSecurityManager::GetKeyPath(RdbSecurityManager::KeyFileType keyType, std::string &keyPath) +{ + if (keyType == KeyFileType::PUB_KEY_FILE) { + keyPath = keyPath_; + } else { + keyPath = newKeyPath_; + } +} + +void RdbSecurityManager::DelRdbSecretDataFile(RdbSecurityManager::KeyFileType keyFile) +{ + std::string keyPath; + GetKeyPath(keyFile, keyPath); + SqliteDatabaseUtils::DeleteFile(keyPath); +} + +void RdbSecurityManager::UpdateKeyFile() +{ + if (!SqliteDatabaseUtils::RenameFile(newKeyPath_, keyPath_)) { + LOG_ERROR("Rename key file failed."); + return; + } } } // namespace NativeRdb } // namespace OHOS diff --git a/relational_store/frameworks/native/rdb/src/rdb_store_config.cpp b/relational_store/frameworks/native/rdb/src/rdb_store_config.cpp index b922dda1..23b61174 100644 --- a/relational_store/frameworks/native/rdb/src/rdb_store_config.cpp +++ b/relational_store/frameworks/native/rdb/src/rdb_store_config.cpp @@ -45,6 +45,7 @@ RdbStoreConfig::RdbStoreConfig(const std::string &name, StorageMode storageMode, syncMode(syncMode), readOnly(isReadOnly), databaseFileType(databaseFileType), + encryptKey_(encryptKey), securityLevel(securityLevel), isCreateNecessary_(isCreateNecessary), autoCheck(autoCheck), @@ -54,7 +55,10 @@ RdbStoreConfig::RdbStoreConfig(const std::string &name, StorageMode storageMode, { } -RdbStoreConfig::~RdbStoreConfig() = default; +RdbStoreConfig::~RdbStoreConfig() +{ + ClearEncryptKey(); +} /** * Obtains the database name. @@ -372,4 +376,19 @@ void RdbStoreConfig::SetReadConSize(int readConSize) { readConSize_= readConSize; } + +void RdbStoreConfig::SetEncryptKey(const std::vector &encryptKey) +{ + encryptKey_ = encryptKey; +} + +std::vector RdbStoreConfig::GetEncryptKey() const +{ + return encryptKey_; +} + +void RdbStoreConfig::ClearEncryptKey() +{ + encryptKey_.assign(encryptKey_.size(), 0); +} } // namespace OHOS::NativeRdb diff --git a/relational_store/frameworks/native/rdb/src/rdb_store_impl.cpp b/relational_store/frameworks/native/rdb/src/rdb_store_impl.cpp index 44664c97..68d48dc0 100644 --- a/relational_store/frameworks/native/rdb/src/rdb_store_impl.cpp +++ b/relational_store/frameworks/native/rdb/src/rdb_store_impl.cpp @@ -36,9 +36,12 @@ #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) #include "iresult_set.h" +#include "rdb_device_manager_adapter.h" #include "rdb_manager.h" +#include "relational_store_manager.h" #include "rdb_security_manager.h" #include "result_set_proxy.h" +#include "runtime_config.h" #include "sqlite_shared_result_set.h" #endif @@ -62,6 +65,7 @@ std::shared_ptr RdbStoreImpl::Open(const RdbStoreConfig &config, int & int RdbStoreImpl::InnerOpen(const RdbStoreConfig &config) { + LOG_INFO("open %{public}s.", SqliteUtils::Anonymous(config.GetPath()).c_str()); int errCode = E_OK; connectionPool = SqliteConnectionPool::Create(config, errCode); if (connectionPool == nullptr) { @@ -86,14 +90,16 @@ int RdbStoreImpl::InnerOpen(const RdbStoreConfig &config) syncerParam_.password_ = {}; // open uri share if (!config.GetUri().empty()) { - auto service = DistributedRdb::RdbManager::GetRdbService(syncerParam_); - if (service == nullptr) { - LOG_ERROR("RdbStoreImpl::InnerOpen get service failed"); - return -1; + std::shared_ptr service = nullptr; + errCode = DistributedRdb::RdbManager::GetRdbService(syncerParam_, service); + if (errCode != E_OK) { + LOG_ERROR("RdbStoreImpl::InnerOpen get service failed, err is %{public}d.", errCode); + return E_OK; } - if (service->CreateRDBTable(syncerParam_, config.GetWritePermission(), config.GetReadPermission()) != E_OK) { + errCode = service->CreateRDBTable(syncerParam_, config.GetWritePermission(), config.GetReadPermission()); + if (errCode != E_OK) { LOG_ERROR("RdbStoreImpl::InnerOpen service CreateRDBTable failed"); - return -1; + return E_OK; } isShared_ = true; } @@ -110,12 +116,11 @@ RdbStoreImpl::RdbStoreImpl() RdbStoreImpl::~RdbStoreImpl() { delete connectionPool; - threadMap.clear(); - idleSessions.clear(); #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) if (isShared_) { - auto service = DistributedRdb::RdbManager::GetRdbService(syncerParam_); - if (service == nullptr) { + std::shared_ptr service = nullptr; + int errCode = DistributedRdb::RdbManager::GetRdbService(syncerParam_, service); + if (errCode != E_OK) { LOG_ERROR("RdbStoreImpl::~RdbStoreImpl get service failed"); return; } @@ -147,17 +152,24 @@ int RdbStoreImpl::BatchInsert(int64_t &outInsertNum, const std::string &table, return E_OK; } // prepare batch data & sql - std::map valuesMap; + std::vector>> vecVectorObj; for (auto iter = initialBatchValues.begin(); iter != initialBatchValues.end(); iter++) { - (*iter).GetAll(valuesMap); - vecVectorObj.push_back(GetInsertParams(valuesMap, table)); - valuesMap.clear(); + auto values = (*iter).GetAll(); + vecVectorObj.push_back(GetInsertParams(values, table)); } // prepare BeginTransaction - connectionPool->AcquireTransaction(); + int errCode = connectionPool->AcquireTransaction(); + if (errCode != E_OK) { + return errCode; + } + SqliteConnection *connection = connectionPool->AcquireConnection(false); + if (connection == nullptr) { + return E_CON_OVER_LIMIT; + } + if (connection->IsInTransaction()) { connectionPool->ReleaseTransaction(); connectionPool->ReleaseConnection(connection); @@ -166,7 +178,7 @@ int RdbStoreImpl::BatchInsert(int64_t &outInsertNum, const std::string &table, } BaseTransaction transaction(0); connection->SetInTransaction(true); - int errCode = connection->ExecuteSql(transaction.GetTransactionStr()); + errCode = connection->ExecuteSql(transaction.GetTransactionStr()); if (errCode != E_OK) { LOG_ERROR("BeginTransaction with error code %{public}d.", errCode); connection->SetInTransaction(false); @@ -237,22 +249,26 @@ int RdbStoreImpl::InsertWithConflictResolution(int64_t &outRowId, const std::str std::stringstream sql; sql << "INSERT" << conflictClause << " INTO " << table << '('; - std::map valuesMap; - initialValues.GetAll(valuesMap); std::vector bindArgs; - for (auto iter = valuesMap.begin(); iter != valuesMap.end(); iter++) { - sql << ((iter == valuesMap.begin()) ? "" : ","); - sql << iter->first; // columnName - bindArgs.push_back(iter->second); // columnValue + const char *split = ""; + for (auto &[key, val] : initialValues.values_) { + sql << split; + sql << key; // columnName + bindArgs.push_back(val); // columnValue + split = ","; } sql << ") VALUES ("; - for (size_t i = 0; i < valuesMap.size(); i++) { + for (size_t i = 0; i < initialValues.Size(); i++) { sql << ((i == 0) ? "?" : ",?"); } sql << ')'; SqliteConnection *connection = connectionPool->AcquireConnection(false); + if (connection == nullptr) { + return E_CON_OVER_LIMIT; + } + errCode = connection->ExecuteForLastInsertedRowId(outRowId, sql.str(), bindArgs); connectionPool->ReleaseConnection(connection); @@ -293,13 +309,13 @@ int RdbStoreImpl::UpdateWithConflictResolution(int &changedRows, const std::stri std::stringstream sql; sql << "UPDATE" << conflictClause << " " << table << " SET "; - std::map valuesMap; - values.GetAll(valuesMap); std::vector bindArgs; - for (auto iter = valuesMap.begin(); iter != valuesMap.end(); iter++) { - sql << ((iter == valuesMap.begin()) ? "" : ","); - sql << iter->first << "=?"; // columnName - bindArgs.push_back(iter->second); // columnValue + const char * split = ""; + for (auto &[key, val] : values.values_) { + sql << split; + sql << key << "=?"; // columnName + bindArgs.push_back(val); // columnValue + split = ","; } if (whereClause.empty() == false) { @@ -311,6 +327,10 @@ int RdbStoreImpl::UpdateWithConflictResolution(int &changedRows, const std::stri } SqliteConnection *connection = connectionPool->AcquireConnection(false); + if (connection == nullptr) { + return E_CON_OVER_LIMIT; + } + errCode = connection->ExecuteForChangedRowCount(changedRows, sql.str(), bindArgs); connectionPool->ReleaseConnection(connection); @@ -342,6 +362,10 @@ int RdbStoreImpl::Delete(int &deletedRows, const std::string &table, const std:: } SqliteConnection *connection = connectionPool->AcquireConnection(false); + if (connection == nullptr) { + return E_CON_OVER_LIMIT; + } + int errCode = connection->ExecuteForChangedRowCount(deletedRows, sql.str(), bindArgs); connectionPool->ReleaseConnection(connection); @@ -353,7 +377,6 @@ std::unique_ptr RdbStoreImpl::Query( const AbsRdbPredicates &predicates, const std::vector columns) { DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__)); - LOG_DEBUG("RdbStoreImpl::Query on called."); std::vector selectionArgs = predicates.GetWhereArgs(); std::string sql = SqliteSqlBuilder::BuildQueryString(predicates, columns); return QuerySql(sql, selectionArgs); @@ -363,21 +386,20 @@ std::unique_ptr RdbStoreImpl::QueryByStep( const AbsRdbPredicates &predicates, const std::vector columns) { DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__)); - LOG_DEBUG("RdbStoreImpl::QueryByStep on called."); std::vector selectionArgs = predicates.GetWhereArgs(); std::string sql = SqliteSqlBuilder::BuildQueryString(predicates, columns); return QueryByStep(sql, selectionArgs); } std::shared_ptr RdbStoreImpl::RemoteQuery(const std::string &device, - const AbsRdbPredicates &predicates, const std::vector &columns) + const AbsRdbPredicates &predicates, const std::vector &columns, int &errCode) { DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__)); - LOG_DEBUG("RdbStoreImpl::RemoteQuery on called."); std::vector selectionArgs = predicates.GetWhereArgs(); std::string sql = SqliteSqlBuilder::BuildQueryString(predicates, columns); - auto service = DistributedRdb::RdbManager::GetRdbService(syncerParam_); - if (service == nullptr) { + std::shared_ptr service = nullptr; + errCode = DistributedRdb::RdbManager::GetRdbService(syncerParam_, service); + if (errCode != E_OK) { LOG_ERROR("RdbStoreImpl::RemoteQuery get service failed"); return nullptr; } @@ -500,6 +522,10 @@ int RdbStoreImpl::ExecuteForLastInsertedRowId(int64_t &outValue, const std::stri const std::vector &bindArgs) { SqliteConnection *connection = connectionPool->AcquireConnection(false); + if (connection == nullptr) { + return E_CON_OVER_LIMIT; + } + int errCode = connection->ExecuteForLastInsertedRowId(outValue, sql, bindArgs); connectionPool->ReleaseConnection(connection); return errCode; @@ -510,6 +536,10 @@ int RdbStoreImpl::ExecuteForChangedRowCount(int64_t &outValue, const std::string { int changeRow = 0; SqliteConnection *connection = connectionPool->AcquireConnection(false); + if (connection == nullptr) { + return E_CON_OVER_LIMIT; + } + int errCode = connection->ExecuteForChangedRowCount(changeRow, sql, bindArgs); connectionPool->ReleaseConnection(connection); outValue = changeRow; @@ -522,7 +552,7 @@ int RdbStoreImpl::ExecuteForChangedRowCount(int64_t &outValue, const std::string int RdbStoreImpl::Backup(const std::string databasePath, const std::vector destEncryptKey) { if (databasePath.empty()) { - LOG_ERROR("Backup:Empty databasePath."); + LOG_ERROR("Empty databasePath."); return E_INVALID_FILE_PATH; } std::string backupFilePath; @@ -530,13 +560,13 @@ int RdbStoreImpl::Backup(const std::string databasePath, const std::vector bindArgs; bindArgs.push_back(ValueObject(backupFilePath)); @@ -598,6 +628,10 @@ int RdbStoreImpl::BeginExecuteSql(const std::string &sql, SqliteConnection **con bool assumeReadOnly = SqliteUtils::IsSqlReadOnly(type); bool isReadOnly = false; *connection = connectionPool->AcquireConnection(assumeReadOnly); + if (*connection == nullptr) { + return E_CON_OVER_LIMIT; + } + int errCode = (*connection)->Prepare(sql, isReadOnly); if (errCode != 0) { connectionPool->ReleaseConnection(*connection); @@ -607,6 +641,10 @@ int RdbStoreImpl::BeginExecuteSql(const std::string &sql, SqliteConnection **con if (isReadOnly == (*connection)->IsWriteConnection()) { connectionPool->ReleaseConnection(*connection); *connection = connectionPool->AcquireConnection(isReadOnly); + if (*connection == nullptr) { + return E_CON_OVER_LIMIT; + } + if (!isReadOnly && !(*connection)->IsWriteConnection()) { LOG_ERROR("StoreSession BeginExecutea : read connection can not execute write operation"); connectionPool->ReleaseConnection(*connection); @@ -625,6 +663,10 @@ bool RdbStoreImpl::IsHoldingConnection() int RdbStoreImpl::GiveConnectionTemporarily(int64_t milliseconds) { SqliteConnection *connection = connectionPool->AcquireConnection(false); + if (connection == nullptr) { + return E_CON_OVER_LIMIT; + } + if (connection->IsInTransaction()) { return E_STORE_SESSION_NOT_GIVE_CONNECTION_TEMPORARILY; } @@ -713,6 +755,10 @@ int RdbStoreImpl::BeginTransaction() DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__)); BaseTransaction transaction(connectionPool->getTransactionStack().size()); SqliteConnection *connection = connectionPool->AcquireConnection(false); + if (connection == nullptr) { + return E_CON_OVER_LIMIT; + } + int errCode = connection->ExecuteSql(transaction.GetTransactionStr()); connectionPool->ReleaseConnection(connection); if (errCode != E_OK) { @@ -740,6 +786,10 @@ int RdbStoreImpl::RollBack() connectionPool->getTransactionStack().top().SetChildFailure(true); } SqliteConnection *connection = connectionPool->AcquireConnection(false); + if (connection == nullptr) { + return E_CON_OVER_LIMIT; + } + int errCode = connection->ExecuteSql(transaction.GetRollbackStr()); connectionPool->ReleaseConnection(connection); if (connectionPool->getTransactionStack().empty()) { @@ -770,6 +820,10 @@ int RdbStoreImpl::Commit() } SqliteConnection *connection = connectionPool->AcquireConnection(false); + if (connection == nullptr) { + return E_CON_OVER_LIMIT; + } + int errCode = connection->ExecuteSql(sqlStr); connectionPool->ReleaseConnection(connection); connection->SetInTransaction(false); @@ -795,7 +849,13 @@ int RdbStoreImpl::FreeTransaction(SqliteConnection *connection, const std::strin bool RdbStoreImpl::IsInTransaction() { - return connectionPool->AcquireConnection(false)->IsInTransaction(); + bool res = true; + auto connection = connectionPool->AcquireConnection(false); + if (connection != nullptr) { + res = connection->IsInTransaction(); + connectionPool->ReleaseConnection(connection); + } + return res; } int RdbStoreImpl::CheckAttach(const std::string &sql) @@ -815,6 +875,10 @@ int RdbStoreImpl::CheckAttach(const std::string &sql) bool isRead = SqliteDatabaseUtils::BeginExecuteSql(GlobalExpr::PRAGMA_JOUR_MODE_EXP); SqliteConnection *connection = connectionPool->AcquireConnection(isRead); + if (connection == nullptr) { + return E_CON_OVER_LIMIT; + } + int errCode = connection->ExecuteGetString(journalMode, GlobalExpr::PRAGMA_JOUR_MODE_EXP, std::vector()); connectionPool->ReleaseConnection(connection); @@ -863,13 +927,13 @@ bool RdbStoreImpl::PathToRealPath(const std::string &path, std::string &realPath } #else if (realpath(path.c_str(), tmpPath) == NULL) { - LOG_ERROR("path to realpath error"); + LOG_ERROR("path (%{public}s) to realpath error", SqliteUtils::Anonymous(path).c_str()); return false; } #endif realPath = tmpPath; if (access(realPath.c_str(), F_OK) != 0) { - LOG_ERROR("check realpath (%{public}s) error", realPath.c_str()); + LOG_ERROR("check realpath (%{public}s) error", SqliteUtils::Anonymous(realPath).c_str()); return false; } return true; @@ -1001,12 +1065,12 @@ std::unique_ptr RdbStoreImpl::QueryByStep(const std::string &sql, } #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) -bool RdbStoreImpl::SetDistributedTables(const std::vector &tables) +int RdbStoreImpl::SetDistributedTables(const std::vector &tables) { DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__)); if (tables.empty()) { LOG_WARN("The distributed tables to be set is empty."); - return true; + return E_OK; } if (isEncrypt_) { bool status = false; @@ -1019,16 +1083,17 @@ bool RdbStoreImpl::SetDistributedTables(const std::vector &tables) } } - auto service = DistributedRdb::RdbManager::GetRdbService(syncerParam_); - if (service == nullptr) { - return false; + std::shared_ptr service = nullptr; + int errCode = DistributedRdb::RdbManager::GetRdbService(syncerParam_, service); + if (errCode != E_OK) { + return errCode; } int32_t errorCode = service->SetDistributedTables(syncerParam_, tables); if (errorCode != E_OK) { LOG_ERROR("Fail to set distributed tables, error=%{public}d", errorCode); syncerParam_.password_.assign(syncerParam_.password_.size(), 0); syncerParam_.password_.clear(); - return false; + return errorCode; } if (isEncrypt_) { @@ -1037,53 +1102,66 @@ bool RdbStoreImpl::SetDistributedTables(const std::vector &tables) RdbSecurityManager::GetInstance().SetKeyDistributedStatus( RdbSecurityManager::KeyFileType::PUB_KEY_FILE, true); } - return true; + return E_OK; } -std::string RdbStoreImpl::ObtainDistributedTableName(const std::string &device, const std::string &table) +std::string RdbStoreImpl::ObtainDistributedTableName(const std::string &device, const std::string &table, int &errCode) { DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__)); - auto service = DistributedRdb::RdbManager::GetRdbService(syncerParam_); - if (service == nullptr) { + + std::string uuid; + DeviceManagerAdaptor::RdbDeviceManagerAdaptor &deviceManager = + DeviceManagerAdaptor::RdbDeviceManagerAdaptor::GetInstance(syncerParam_.bundleName_); + errCode = deviceManager.GetEncryptedUuidByNetworkId(device, uuid); + if (errCode != E_OK) { + LOG_ERROR("GetUuid is failed"); return ""; } - auto distTable = service->ObtainDistributedTableName(device, table); - return distTable; + +// auto translateCall = [uuid](const std::string &oriDevId, const DistributedDB::StoreInfo &info) { +// return uuid; +// }; +// DistributedDB::RuntimeConfig::SetTranslateToDeviceIdCallback(translateCall); + + return DistributedDB::RelationalStoreManager::GetDistributedTableName(uuid, table); } -bool RdbStoreImpl::Sync(const SyncOption &option, const AbsRdbPredicates &predicate, const SyncCallback &callback) +int RdbStoreImpl::Sync(const SyncOption &option, const AbsRdbPredicates &predicate, const SyncCallback &callback) { DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__)); - auto service = DistributedRdb::RdbManager::GetRdbService(syncerParam_); - if (service == nullptr) { - return false; + std::shared_ptr service = nullptr; + int errCode = DistributedRdb::RdbManager::GetRdbService(syncerParam_, service); + if (errCode != E_OK) { + LOG_ERROR("GetRdbService is failed, err is %{public}d.", errCode); + return errCode; } - if (service->Sync(syncerParam_, option, predicate.GetDistributedPredicates(), callback) != 0) { - LOG_ERROR("failed"); - return false; + errCode = service->Sync(syncerParam_, option, predicate.GetDistributedPredicates(), callback); + if (errCode != E_OK) { + LOG_ERROR("Sync is failed, err is %{public}d.", errCode); + return errCode; } - LOG_INFO("success"); - return true; + return E_OK; } -bool RdbStoreImpl::Subscribe(const SubscribeOption &option, RdbStoreObserver *observer) +int RdbStoreImpl::Subscribe(const SubscribeOption &option, RdbStoreObserver *observer) { - LOG_INFO("enter"); - auto service = DistributedRdb::RdbManager::GetRdbService(syncerParam_); - if (service == nullptr) { - return false; + std::shared_ptr service = nullptr; + int errCode = DistributedRdb::RdbManager::GetRdbService(syncerParam_, service); + if (errCode != E_OK) { + return errCode; } - return service->Subscribe(syncerParam_, option, observer) == 0; + return service->Subscribe(syncerParam_, option, observer); } -bool RdbStoreImpl::UnSubscribe(const SubscribeOption &option, RdbStoreObserver *observer) +int RdbStoreImpl::UnSubscribe(const SubscribeOption &option, RdbStoreObserver *observer) { LOG_INFO("enter"); - auto service = DistributedRdb::RdbManager::GetRdbService(syncerParam_); - if (service == nullptr) { - return false; + std::shared_ptr service = nullptr; + int errCode = DistributedRdb::RdbManager::GetRdbService(syncerParam_, service); + if (errCode != E_OK) { + return errCode; } - return service->UnSubscribe(syncerParam_, option, observer) == 0; + return service->UnSubscribe(syncerParam_, option, observer); } bool RdbStoreImpl::DropDeviceData(const std::vector &devices, const DropOption &option) diff --git a/relational_store/frameworks/native/rdb/src/rdb_types_util.cpp b/relational_store/frameworks/native/rdb/src/rdb_types_util.cpp index 2521f273..f24c57d6 100644 --- a/relational_store/frameworks/native/rdb/src/rdb_types_util.cpp +++ b/relational_store/frameworks/native/rdb/src/rdb_types_util.cpp @@ -81,11 +81,21 @@ template<> bool ITypesUtil::Unmarshalling(ValueObject &output, MessageParcel &da template<> bool ITypesUtil::Marshalling(const ValuesBucket &input, MessageParcel &data) { - return ITypesUtil::Marshal(data, input.valuesMap); + return ITypesUtil::Marshal(data, input.values_); } template<> bool ITypesUtil::Unmarshalling(ValuesBucket &output, MessageParcel &data) { - return ITypesUtil::Marshal(data, output.valuesMap); + return ITypesUtil::Marshal(data, output.values_); +} +template<> +bool ITypesUtil::Marshalling(const Asset &input, MessageParcel &data) +{ + return ITypesUtil::Marshal(data, input.version, input.name, input.size, input.modifyTime, input.uri); +} +template<> +bool ITypesUtil::Unmarshalling(Asset &output, MessageParcel &data) +{ + return ITypesUtil::Unmarshal(data, output.version, output.name, output.size, output.modifyTime, output.uri); } } \ No newline at end of file diff --git a/relational_store/frameworks/native/rdb/src/share_block.cpp b/relational_store/frameworks/native/rdb/src/share_block.cpp index 2015e001..32b75c3c 100644 --- a/relational_store/frameworks/native/rdb/src/share_block.cpp +++ b/relational_store/frameworks/native/rdb/src/share_block.cpp @@ -116,7 +116,6 @@ void FillSharedBlockOpt(SharedBlockInfo *info) while (!gotException) { int err = sqlite3_step(info->statement); if (err == SQLITE_DONE) { - LOG_WARN("Processed all rows after optimization."); break; } else if (err == SQLITE_LOCKED || err == SQLITE_BUSY) { LOG_WARN("Database locked, retrying"); diff --git a/relational_store/frameworks/native/rdb/src/sqlite_config.cpp b/relational_store/frameworks/native/rdb/src/sqlite_config.cpp index dc7afbf4..00c914bf 100644 --- a/relational_store/frameworks/native/rdb/src/sqlite_config.cpp +++ b/relational_store/frameworks/native/rdb/src/sqlite_config.cpp @@ -31,6 +31,7 @@ SqliteConfig::SqliteConfig(const RdbStoreConfig &config) } #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) isEncrypt = config.IsEncrypt(); + encryptKey_ = config.GetEncryptKey(); isCreateNecessary = config.IsCreateNecessary(); #endif @@ -41,7 +42,12 @@ SqliteConfig::SqliteConfig(const RdbStoreConfig &config) this->readConSize_ = config.GetReadConSize(); } -SqliteConfig::~SqliteConfig() = default; +SqliteConfig::~SqliteConfig() +{ +#if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) + ClearEncryptKey(); +#endif +} std::string SqliteConfig::GetPath() const { @@ -124,7 +130,7 @@ void SqliteConfig::SetReadConSize(int readConSize) } #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) -bool SqliteConfig::IsEncrypt() const +bool SqliteConfig::IsAutoEncrypt() const { return isEncrypt; } @@ -143,6 +149,21 @@ void SqliteConfig::SetCreateNecessary(bool CreateNecessary) { this->isCreateNecessary = CreateNecessary; } + +void SqliteConfig::SetEncryptKey(const std::vector &encryptKey) +{ + encryptKey_ = encryptKey; +} + +std::vector SqliteConfig::GetEncryptKey() const +{ + return encryptKey_; +} + +void SqliteConfig::ClearEncryptKey() +{ + encryptKey_.assign(encryptKey_.size(), 0); +} #endif } // namespace NativeRdb } // namespace OHOS \ No newline at end of file diff --git a/relational_store/frameworks/native/rdb/src/sqlite_connection.cpp b/relational_store/frameworks/native/rdb/src/sqlite_connection.cpp index 06724dc3..49014e8c 100644 --- a/relational_store/frameworks/native/rdb/src/sqlite_connection.cpp +++ b/relational_store/frameworks/native/rdb/src/sqlite_connection.cpp @@ -45,11 +45,16 @@ namespace NativeRdb { #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) // error status const int ERROR_STATUS = -1; +using RdbKeyFile = RdbSecurityManager::KeyFileType; #endif SqliteConnection *SqliteConnection::Open(const SqliteConfig &config, bool isWriteConnection, int &errCode) { - auto connection = new SqliteConnection(isWriteConnection); + auto connection = new (std::nothrow) SqliteConnection(isWriteConnection); + if (connection == nullptr) { + LOG_ERROR("SqliteConnection::Open new failed, connection is nullptr"); + return nullptr; + } errCode = connection->InnerOpen(config); if (errCode != E_OK) { delete connection; @@ -123,9 +128,11 @@ int SqliteConnection::InnerOpen(const SqliteConfig &config) return errCode; } - errCode = sqlite3_wal_checkpoint_v2(dbHandle, nullptr, SQLITE_CHECKPOINT_TRUNCATE, nullptr, nullptr); - if (errCode != SQLITE_OK) { - LOG_WARN("sqlite checkpoint errCode is %{public}d", errCode); + if (isWriteConnection) { + errCode = sqlite3_wal_checkpoint_v2(dbHandle, nullptr, SQLITE_CHECKPOINT_TRUNCATE, nullptr, nullptr); + if (errCode != SQLITE_OK) { + LOG_WARN("sqlite checkpoint errCode is %{public}d", errCode); + } } filePath = dbPath; @@ -145,14 +152,12 @@ int SqliteConnection::Config(const SqliteConfig &config) return errCode; } -#if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) - errCode = ManageKey(config); + errCode = SetEncryptAlgo(config); if (errCode != E_OK) { return errCode; } -#endif - errCode = SetEncryptAlgo(config); + errCode = SetEncryptKey(config); if (errCode != E_OK) { return errCode; } @@ -217,31 +222,68 @@ int SqliteConnection::SetPageSize(const SqliteConfig &config) int SqliteConnection::SetEncryptAlgo(const SqliteConfig &config) { int errCode = E_OK; - if (config.GetEncryptAlgo().compare(GlobalExpr::ENCRYPT_ALGO) == 0) { +#if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) + if (!config.IsAutoEncrypt() && config.GetEncryptKey().empty()) { return errCode; } - - // first to get the value, then to set algo +#endif std::string sqlStr = "PRAGMA codec_hmac_algo=" + config.GetEncryptAlgo(); errCode = ExecuteSql(sqlStr); if (errCode != E_OK) { LOG_ERROR("SqliteConnection SetEncryptAlgorithm fail, err = %{public}d", errCode); + return errCode; } + + sqlStr = "PRAGMA codec_rekey_hmac_algo=" + config.GetEncryptAlgo(); + errCode = ExecuteSql(sqlStr); + if (errCode != E_OK) { + LOG_ERROR("SqliteConnection set rekey Algo fail, err = %{public}d", errCode); + return errCode; + } + return errCode; } -int SqliteConnection::SetEncryptKey(const std::vector &encryptKey) +int SqliteConnection::SetEncryptKey(const SqliteConfig &config) { - if (encryptKey.empty()) { +#if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) + std::vector key; + RdbPassword rdbPwd; + if (!config.GetEncryptKey().empty() && !config.IsAutoEncrypt()) { + key = config.GetEncryptKey(); + } else if (config.IsAutoEncrypt()) { + rdbPwd = RdbSecurityManager::GetInstance().GetRdbPassword(RdbKeyFile::PUB_KEY_FILE); + key = std::vector(rdbPwd.GetData(), rdbPwd.GetData() + rdbPwd.GetSize()); + } else { return E_OK; } - int errCode = sqlite3_key(dbHandle, static_cast(encryptKey.data()), encryptKey.size()); + int errCode = sqlite3_key(dbHandle, static_cast(key.data()), static_cast(key.size())); + key.assign(key.size(), 0); if (errCode != SQLITE_OK) { LOG_ERROR("SqliteConnection SetEncryptKey fail, err = %{public}d", errCode); return SQLiteError::ErrNo(errCode); } + if (rdbPwd.isKeyExpired) { + rdbPwd = RdbSecurityManager::GetInstance().GetRdbPassword(RdbKeyFile::PUB_KEY_FILE_NEW_KEY); + if (!rdbPwd.IsValid()) { + RdbSecurityManager::GetInstance().DelRdbSecretDataFile(RdbKeyFile::PUB_KEY_FILE_NEW_KEY); + LOG_ERROR("new key is not valid."); + return E_OK; + } + key = std::vector(rdbPwd.GetData(), rdbPwd.GetData() + rdbPwd.GetSize()); + errCode = sqlite3_rekey(dbHandle, static_cast(key.data()), static_cast(key.size())); + key.assign(key.size(), 0); + if (errCode != SQLITE_OK) { + LOG_ERROR("ReKey failed, err = %{public}d", errCode); + RdbSecurityManager::GetInstance().DelRdbSecretDataFile(RdbKeyFile::PUB_KEY_FILE_NEW_KEY); + return E_OK; + } + + RdbSecurityManager::GetInstance().UpdateKeyFile(); + } +#endif return E_OK; } @@ -253,7 +295,6 @@ int SqliteConnection::SetPersistWal() LOG_ERROR("failed"); return E_SET_PERSIST_WAL; } - LOG_INFO("success"); return E_OK; } @@ -264,7 +305,6 @@ int SqliteConnection::SetBusyTimeout(int timeout) LOG_ERROR("set buys timeout failed, errCode=%{public}d", errCode); return errCode; } - LOG_INFO("success"); return E_OK; } @@ -740,52 +780,6 @@ int SqliteConnection::ExecuteForSharedBlock(int &rowNum, std::string sql, const errCode = statement.ResetStatementAndClearBindings(); return errCode; } - -int SqliteConnection::ManageKey(const SqliteConfig &config) -{ - if (!config.IsEncrypt()) { - return E_OK; - } - bool isKeyFileExists = - RdbSecurityManager::GetInstance().CheckKeyDataFileExists(RdbSecurityManager::KeyFileType::PUB_KEY_FILE); - if (!isKeyFileExists) { - if (InitKey() != E_OK) { - return E_ERROR; - } - } - - return GetKeyFromFile(); -} - -int SqliteConnection::InitKey() -{ - LOG_INFO("Init pub_key file"); - std::vector key = RdbSecurityManager::GetInstance().GenerateRandomNum(RdbSecurityManager::RDB_KEY_SIZE); - if (!RdbSecurityManager::GetInstance().SaveSecretKeyToFile(RdbSecurityManager::KeyFileType::PUB_KEY_FILE, key)) { - LOG_ERROR("Init key SaveSecretKeyToFile failed!"); - key.assign(key.size(), 0); - return E_ERROR; - } - key.assign(key.size(), 0); - return E_OK; -} - -int SqliteConnection::GetKeyFromFile() -{ - LOG_INFO("Get key from pub_key file"); - RdbPassword key = RdbSecurityManager::GetInstance().GetRdbPassword(RdbSecurityManager::KeyFileType::PUB_KEY_FILE); - if (key.GetSize() == 0) { - return E_ERROR; - } - auto keyTemp = std::vector(key.GetData(), key.GetData() + key.GetSize()); - if (SetEncryptKey(keyTemp) != E_OK) { - keyTemp.assign(keyTemp.size(), 0); - return E_ERROR; - } - - keyTemp.assign(keyTemp.size(), 0); - return E_OK; -} #endif void SqliteConnection::SetInTransaction(bool transaction) @@ -805,7 +799,7 @@ int SqliteConnection::LimitWalSize() } std::string walName = sqlite3_filename_wal(sqlite3_db_filename(dbHandle, "main")); - if (SqliteUtils::GetFileSize(walName) < GlobalExpr::DB_WAL_SIZE_LIMIT) { + if (SqliteUtils::GetFileSize(walName) <= GlobalExpr::DB_WAL_SIZE_LIMIT) { return E_OK; } @@ -815,8 +809,9 @@ int SqliteConnection::LimitWalSize() } int fileSize = SqliteUtils::GetFileSize(walName); - if (fileSize >= GlobalExpr::DB_WAL_SIZE_LIMIT) { - LOG_ERROR("the WAL file size over default limit, size: %{public}d", fileSize); + if (fileSize > GlobalExpr::DB_WAL_SIZE_LIMIT) { + LOG_ERROR("the WAL file size over default limit, %{public}s size is %{public}d", + SqliteUtils::Anonymous(walName).c_str(), fileSize); return E_WAL_SIZE_OVER_LIMIT; } diff --git a/relational_store/frameworks/native/rdb/src/sqlite_connection_pool.cpp b/relational_store/frameworks/native/rdb/src/sqlite_connection_pool.cpp index fde0b473..9cae45d7 100644 --- a/relational_store/frameworks/native/rdb/src/sqlite_connection_pool.cpp +++ b/relational_store/frameworks/native/rdb/src/sqlite_connection_pool.cpp @@ -32,9 +32,15 @@ namespace OHOS { namespace NativeRdb { +constexpr std::chrono::seconds WAIT_CONNECT_TIMEOUT(2); + SqliteConnectionPool *SqliteConnectionPool::Create(const RdbStoreConfig &storeConfig, int &errCode) { - auto pool = new SqliteConnectionPool(storeConfig); + auto pool = new (std::nothrow) SqliteConnectionPool(storeConfig); + if (pool == nullptr) { + LOG_ERROR("SqliteConnectionPool::Create new failed, pool is nullptr"); + return nullptr; + } errCode = pool->Init(); if (errCode != E_OK) { delete pool; @@ -114,10 +120,8 @@ void SqliteConnectionPool::CloseAllConnections() SqliteConnection *SqliteConnectionPool::AcquireConnection(bool isReadOnly) { if (isReadOnly && readConnectionCount != 0) { - LOG_DEBUG("AcquireReadConnection"); return AcquireReadConnection(); } else { - LOG_DEBUG("AcquireWriteConnection"); return AcquireWriteConnection(); } } @@ -133,21 +137,24 @@ void SqliteConnectionPool::ReleaseConnection(SqliteConnection *connection) SqliteConnection *SqliteConnectionPool::AcquireWriteConnection() { - LOG_DEBUG("begin"); std::unique_lock lock(writeMutex); - writeCondition.wait(lock, [&] { return !writeConnectionUsed; }); - writeConnectionUsed = true; - LOG_DEBUG("end"); - return writeConnection; + if (writeCondition.wait_for(lock, WAIT_CONNECT_TIMEOUT, [this] { return !writeConnectionUsed; })) { + writeConnectionUsed = true; + return writeConnection; + } + LOG_WARN("writeConnection is %{public}d", writeConnectionUsed); + return nullptr; } -void SqliteConnectionPool::AcquireTransaction() +int SqliteConnectionPool::AcquireTransaction() { - LOG_DEBUG("AcquireTransaction begin"); std::unique_lock lock(transMutex); - transCondition.wait(lock, [&] { return !transactionUsed; }); - transactionUsed = true; - LOG_DEBUG("AcquireTransaction end"); + if (transCondition.wait_for(lock, WAIT_CONNECT_TIMEOUT, [this] { return !transactionUsed; })) { + transactionUsed = true; + return E_OK; + } + LOG_WARN("transactionUsed is %{public}d", transactionUsed); + return E_TRANSACTION_IN_EXECUTE; } void SqliteConnectionPool::ReleaseTransaction() @@ -175,11 +182,15 @@ void SqliteConnectionPool::ReleaseWriteConnection() SqliteConnection *SqliteConnectionPool::AcquireReadConnection() { std::unique_lock lock(readMutex); - readCondition.wait(lock, [&] { return idleReadConnectionCount > 0; }); - SqliteConnection *connection = readConnections.back(); - readConnections.pop_back(); - idleReadConnectionCount--; - return connection; + if (readCondition.wait_for(lock, WAIT_CONNECT_TIMEOUT, [this] { return idleReadConnectionCount > 0; })) { + SqliteConnection *connection = readConnections.back(); + readConnections.pop_back(); + idleReadConnectionCount--; + return connection; + } + LOG_WARN("readConnectionCount is %{public}d, idleReadConnectionCount is %{public}d", readConnectionCount, + idleReadConnectionCount); + return nullptr; } /** diff --git a/relational_store/frameworks/native/rdb/src/sqlite_database_utils.cpp b/relational_store/frameworks/native/rdb/src/sqlite_database_utils.cpp index 712d7870..47af023f 100644 --- a/relational_store/frameworks/native/rdb/src/sqlite_database_utils.cpp +++ b/relational_store/frameworks/native/rdb/src/sqlite_database_utils.cpp @@ -24,11 +24,12 @@ #ifdef WINDOWS_PLATFORM #include #endif -#include #include +#include #include "logger.h" #include "rdb_errno.h" +#include "sqlite_utils.h" #ifdef WINDOWS_PLATFORM #define REALPATH(relPath, absPath, ...) (_fullpath(absPath, relPath, ##__VA_ARGS__)) @@ -100,14 +101,15 @@ std::string SqliteDatabaseUtils::StrToUpper(std::string s) void SqliteDatabaseUtils::DeleteFile(std::string &fileName) { if (access(fileName.c_str(), F_OK) != 0) { - LOG_ERROR("File %{private}s does not exist", fileName.c_str()); + LOG_ERROR("access %{public}s errno is %{public}d", SqliteUtils::Anonymous(fileName).c_str(), errno); return; } - if (!remove(fileName.c_str())) { - LOG_ERROR("FileName= %{private}s has been deleted", fileName.c_str()); + + if (remove(fileName.c_str()) != 0) { + LOG_ERROR("remove %{public}s errno is %{public}d", SqliteUtils::Anonymous(fileName).c_str(), errno); return; } - LOG_INFO("Failed to delete File %{private}s", fileName.c_str()); + LOG_INFO("remove %{public}s", SqliteUtils::Anonymous(fileName).c_str()); } /** @@ -116,15 +118,15 @@ void SqliteDatabaseUtils::DeleteFile(std::string &fileName) bool SqliteDatabaseUtils::RenameFile(std::string &oldFileName, std::string &newFileName) { if (access(oldFileName.c_str(), F_OK) != 0) { - LOG_ERROR("File %{private}s does not exist", oldFileName.c_str()); + LOG_ERROR("access %{public}s errno is %{public}d", SqliteUtils::Anonymous(oldFileName).c_str(), errno); return false; } - if (rename(oldFileName.c_str(), newFileName.c_str())) { - LOG_ERROR("Rename oldFileName = %{private}s to newFileName %{private}s", oldFileName.c_str(), - newFileName.c_str()); - return true; + if (rename(oldFileName.c_str(), newFileName.c_str()) != 0) { + LOG_ERROR("Rename %{public}s to %{public}s errno %{public}d", SqliteUtils::Anonymous(oldFileName).c_str(), + SqliteUtils::Anonymous(newFileName).c_str(), errno); + return false; } - return false; + return true; } /** diff --git a/relational_store/frameworks/native/rdb/src/sqlite_shared_result_set.cpp b/relational_store/frameworks/native/rdb/src/sqlite_shared_result_set.cpp index 1db136a2..886012b0 100644 --- a/relational_store/frameworks/native/rdb/src/sqlite_shared_result_set.cpp +++ b/relational_store/frameworks/native/rdb/src/sqlite_shared_result_set.cpp @@ -68,6 +68,10 @@ int SqliteSharedResultSet::GetAllColumnNames(std::vector &columnNam } SqliteConnection *connection = connectionPool_->AcquireConnection(true); + if (connection == nullptr) { + return E_CON_OVER_LIMIT; + } + int errCode = PrepareStep(connection); if (errCode) { connectionPool_->ReleaseConnection(connection); @@ -168,6 +172,9 @@ void SqliteSharedResultSet::FillSharedBlock(int requiredPos) bool isRead = SqliteDatabaseUtils::BeginExecuteSql(qrySql); SqliteConnection* connection = connectionPool_->AcquireConnection(isRead); + if (connection == nullptr) { + return; + } if (rowNum == NO_COUNT) { connection->ExecuteForSharedBlock(rowNum, qrySql, bindArgs, GetBlock(), requiredPos, requiredPos, true); @@ -214,13 +221,5 @@ void SqliteSharedResultSet::Finalize() Close(); } } - -int SqliteSharedResultSet::CheckSession() -{ - if (std::this_thread::get_id() != tid) { - return E_STEP_RESULT_SET_CROSS_THREADS; - } - return E_OK; -} } // namespace NativeRdb } // namespace OHOS \ No newline at end of file diff --git a/relational_store/frameworks/native/rdb/src/sqlite_sql_builder.cpp b/relational_store/frameworks/native/rdb/src/sqlite_sql_builder.cpp index 4781b5ed..836bbe40 100644 --- a/relational_store/frameworks/native/rdb/src/sqlite_sql_builder.cpp +++ b/relational_store/frameworks/native/rdb/src/sqlite_sql_builder.cpp @@ -62,12 +62,12 @@ std::string SqliteSqlBuilder::BuildUpdateString(const ValuesBucket &values, cons .append(" ") .append(tableName) .append(" SET "); - std::map valuesMap; - values.GetAll(valuesMap); - for (auto iter = valuesMap.begin(); iter != valuesMap.end(); iter++) { - sql.append((iter == valuesMap.begin()) ? "" : ","); - sql.append(iter->first).append("=?"); - bindArgs.push_back(iter->second); + const char *split = ""; + for (auto &[key, val] : values.values_) { + sql.append(split); + sql.append(key).append("=?"); + bindArgs.push_back(val); + split = ","; } if (!whereArgs.empty()) { @@ -307,12 +307,12 @@ std::string SqliteSqlBuilder::PredicatesNormalize(const std::string &source, int } auto index = source.rfind("(*"); - if (index != -1) { + if (index != std::string::npos) { return source; } index = source.rfind("."); - if (index == -1) { + if (index == std::string::npos) { return StringUtils::SurroundWithQuote(source, "`"); } diff --git a/relational_store/frameworks/native/rdb/src/sqlite_statement.cpp b/relational_store/frameworks/native/rdb/src/sqlite_statement.cpp index ee454238..1f8e9a4f 100644 --- a/relational_store/frameworks/native/rdb/src/sqlite_statement.cpp +++ b/relational_store/frameworks/native/rdb/src/sqlite_statement.cpp @@ -43,7 +43,7 @@ int SqliteStatement::Prepare(sqlite3 *dbHandle, const std::string &newSql) sqlite3_stmt *stmt = nullptr; int errCode = sqlite3_prepare_v2(dbHandle, newSql.c_str(), newSql.length(), &stmt, nullptr); if (errCode != SQLITE_OK) { - LOG_ERROR("SqliteStatement::Prepare failed err = %{public}d", errCode); + LOG_ERROR("prepare_v2 ret is %{public}d", errCode); if (stmt != nullptr) { sqlite3_finalize(stmt); } @@ -71,7 +71,7 @@ int SqliteStatement::Finalize() columnCount = 0; numParameters = 0; if (errCode != SQLITE_OK) { - LOG_ERROR("SqliteStatement::Finalize failed err = %{public}d", errCode); + LOG_ERROR("finalize ret is %{public}d", errCode); return SQLiteError::ErrNo(errCode); } return E_OK; @@ -98,6 +98,7 @@ int SqliteStatement::BindArguments(const std::vector &bindArgs) con } if (count > numParameters) { + LOG_ERROR("bind args count(%{public}d) > numParameters(%{public}d)", count, numParameters); return E_INVALID_BIND_ARGS_COUNT; } @@ -148,6 +149,7 @@ int SqliteStatement::InnerBindArguments(const std::vector &bindArgs } if (errCode != SQLITE_OK) { + LOG_ERROR("bind ret is %{public}d", errCode); return SQLiteError::ErrNo(errCode); } @@ -165,13 +167,13 @@ int SqliteStatement::ResetStatementAndClearBindings() const int errCode = sqlite3_reset(stmtHandle); if (errCode != SQLITE_OK) { - LOG_ERROR("Reset statement failed. %{public}d", errCode); + LOG_ERROR("reset ret is %{public}d", errCode); return SQLiteError::ErrNo(errCode); } errCode = sqlite3_clear_bindings(stmtHandle); if (errCode != SQLITE_OK) { - LOG_ERROR("Reset clear bindings failed. %{public}d", errCode); + LOG_ERROR("clear_bindings ret is %{public}d", errCode); return SQLiteError::ErrNo(errCode); } @@ -187,6 +189,7 @@ int SqliteStatement::Step() const int SqliteStatement::GetColumnCount(int &count) const { if (stmtHandle == nullptr) { + LOG_ERROR("invalid statement."); return E_INVALID_STATEMENT; } count = columnCount; @@ -199,6 +202,7 @@ int SqliteStatement::GetColumnCount(int &count) const int SqliteStatement::GetNumParameters(int &numParams) const { if (stmtHandle == nullptr) { + LOG_ERROR("invalid statement."); return E_INVALID_STATEMENT; } numParams = numParameters; @@ -208,15 +212,18 @@ int SqliteStatement::GetNumParameters(int &numParams) const int SqliteStatement::GetColumnName(int index, std::string &columnName) const { if (stmtHandle == nullptr) { + LOG_ERROR("invalid statement."); return E_INVALID_STATEMENT; } if (index >= columnCount) { + LOG_ERROR("index (%{public}d) >= columnCount (%{public}d)", index, columnCount); return E_INVALID_COLUMN_INDEX; } const char *name = sqlite3_column_name(stmtHandle, index); if (name == nullptr) { + LOG_ERROR("column_name is null."); return E_ERROR; } columnName = std::string(name); @@ -226,10 +233,12 @@ int SqliteStatement::GetColumnName(int index, std::string &columnName) const int SqliteStatement::GetColumnType(int index, int &columnType) const { if (stmtHandle == nullptr) { + LOG_ERROR("invalid statement."); return E_INVALID_STATEMENT; } if (index >= columnCount) { + LOG_ERROR("index (%{public}d) >= columnCount (%{public}d)", index, columnCount); return E_INVALID_COLUMN_INDEX; } @@ -243,6 +252,7 @@ int SqliteStatement::GetColumnType(int index, int &columnType) const columnType = type; return E_OK; default: + LOG_ERROR("invalid type %{public}d.", type); return E_ERROR; } } @@ -250,15 +260,18 @@ int SqliteStatement::GetColumnType(int index, int &columnType) const int SqliteStatement::GetColumnBlob(int index, std::vector &value) const { if (stmtHandle == nullptr) { + LOG_ERROR("invalid statement."); return E_INVALID_STATEMENT; } if (index >= columnCount) { + LOG_ERROR("index (%{public}d) >= columnCount (%{public}d)", index, columnCount); return E_INVALID_COLUMN_INDEX; } int type = sqlite3_column_type(stmtHandle, index); if (type != SQLITE_BLOB && type != SQLITE_TEXT && type != SQLITE_NULL) { + LOG_ERROR("invalid type %{public}d.", type); return E_INVALID_COLUMN_TYPE; } @@ -319,10 +332,12 @@ int SqliteStatement::GetColumnString(int index, std::string &value) const int SqliteStatement::GetColumnLong(int index, int64_t &value) const { if (stmtHandle == nullptr) { + LOG_ERROR("invalid statement."); return E_INVALID_STATEMENT; } if (index >= columnCount) { + LOG_ERROR("index (%{public}d) >= columnCount (%{public}d)", index, columnCount); return E_INVALID_COLUMN_INDEX; } char *errStr = nullptr; @@ -348,10 +363,12 @@ int SqliteStatement::GetColumnLong(int index, int64_t &value) const int SqliteStatement::GetColumnDouble(int index, double &value) const { if (stmtHandle == nullptr) { + LOG_ERROR("invalid statement."); return E_INVALID_STATEMENT; } if (index >= columnCount) { + LOG_ERROR("index (%{public}d) >= columnCount (%{public}d)", index, columnCount); return E_INVALID_COLUMN_INDEX; } char *ptr = nullptr; @@ -369,6 +386,7 @@ int SqliteStatement::GetColumnDouble(int index, double &value) const } else if (type == SQLITE_BLOB) { return E_INVALID_COLUMN_TYPE; } else { + LOG_ERROR("invalid type %{public}d.", type); return E_ERROR; } diff --git a/relational_store/frameworks/native/rdb/src/sqlite_utils.cpp b/relational_store/frameworks/native/rdb/src/sqlite_utils.cpp index 64516dac..b03226c5 100644 --- a/relational_store/frameworks/native/rdb/src/sqlite_utils.cpp +++ b/relational_store/frameworks/native/rdb/src/sqlite_utils.cpp @@ -42,6 +42,12 @@ const int SqliteUtils::STATEMENT_PRAGMA = 8; const int SqliteUtils::STATEMENT_DDL = 9; const int SqliteUtils::STATEMENT_OTHER = 99; +constexpr int32_t HEAD_SIZE = 3; +constexpr int32_t END_SIZE = 3; +constexpr int32_t MIN_SIZE = HEAD_SIZE + END_SIZE + 3; +constexpr const char *REPLACE_CHAIN = "***"; +constexpr const char *DEFAULT_ANONYMOUS = "******"; + const std::map SqliteUtils::SQL_TYPE_MAP = { { "SEL", SqliteUtils::STATEMENT_SELECT }, { "INS", SqliteUtils::STATEMENT_UPDATE }, @@ -117,6 +123,19 @@ int SqliteUtils::RenameFile(const std::string srcFile, const std::string destFil return rename(srcFile.c_str(), destFile.c_str()); } +std::string SqliteUtils::Anonymous(const std::string &srcFile) +{ + if (srcFile.length() <= HEAD_SIZE) { + return DEFAULT_ANONYMOUS; + } + + if (srcFile.length() < MIN_SIZE) { + return (srcFile.substr(0, HEAD_SIZE) + REPLACE_CHAIN); + } + + return (srcFile.substr(0, HEAD_SIZE) + REPLACE_CHAIN + srcFile.substr(srcFile.length() - END_SIZE, END_SIZE)); +} + int SqliteUtils::GetFileSize(const std::string fileName) { if (fileName.empty() || access(fileName.c_str(), F_OK) != 0) { diff --git a/relational_store/frameworks/native/rdb/src/step_result_set.cpp b/relational_store/frameworks/native/rdb/src/step_result_set.cpp index 88b0610a..4308620f 100644 --- a/relational_store/frameworks/native/rdb/src/step_result_set.cpp +++ b/relational_store/frameworks/native/rdb/src/step_result_set.cpp @@ -47,13 +47,12 @@ StepResultSet::StepResultSet(SqliteConnectionPool *pool, const std::string &sql, StepResultSet::~StepResultSet() { Close(); - connectionPool_->ReleaseConnection(connection_); - connection_ = nullptr; } int StepResultSet::GetAllColumnNames(std::vector &columnNames) { if (isClosed) { + LOG_ERROR("resultSet closed"); return E_STEP_RESULT_CLOSED; } @@ -64,12 +63,14 @@ int StepResultSet::GetAllColumnNames(std::vector &columnNames) int errCode = PrepareStep(); if (errCode) { + LOG_ERROR("PrepareStep ret %{public}d", errCode); return errCode; } int columnCount = 0; errCode = sqliteStatement->GetColumnCount(columnCount); if (errCode) { + LOG_ERROR("GetColumnCount ret %{public}d", errCode); return errCode; } @@ -79,6 +80,7 @@ int StepResultSet::GetAllColumnNames(std::vector &columnNames) errCode = sqliteStatement->GetColumnName(i, columnName); if (errCode) { columnNames.clear(); + LOG_ERROR("GetColumnName ret %{public}d", errCode); return errCode; } columnNames.push_back(columnName); @@ -90,15 +92,18 @@ int StepResultSet::GetAllColumnNames(std::vector &columnNames) int StepResultSet::GetColumnType(int columnIndex, ColumnType &columnType) { if (isClosed) { + LOG_ERROR("resultSet closed"); return E_STEP_RESULT_CLOSED; } if (rowPos_ == INIT_POS) { + LOG_ERROR("query not executed."); return E_STEP_RESULT_QUERY_NOT_EXECUTED; } int sqliteType; int errCode = sqliteStatement->GetColumnType(columnIndex, sqliteType); if (errCode) { + LOG_ERROR("GetColumnType ret %{public}d", errCode); return errCode; } @@ -146,11 +151,13 @@ int StepResultSet::GetRowCount(int &count) */ int StepResultSet::GoToRow(int position) { - if (!connection_) { - return E_ERROR; + if (connection_ == nullptr) { + LOG_ERROR("Failed as too many connections"); + return E_CON_OVER_LIMIT; } // If the moved position is less than zero, reset the result and return an error if (position < 0) { + LOG_ERROR("position %{public}d.", position); Reset(); return E_ERROR; } @@ -164,6 +171,7 @@ int StepResultSet::GoToRow(int position) while (position != rowPos_) { int errCode = GoToNextRow(); if (errCode) { + LOG_ERROR("GoToNextRow ret %{public}d", errCode); return errCode; } } @@ -178,6 +186,7 @@ int StepResultSet::GoToNextRow() { int errCode = PrepareStep(); if (errCode) { + LOG_ERROR("PrepareStep ret %{public}d", errCode); return errCode; } @@ -187,7 +196,7 @@ int StepResultSet::GoToNextRow() while (errCode == SQLITE_LOCKED || errCode == SQLITE_BUSY) { // The table is locked, retry if (retryCount > STEP_QUERY_RETRY_MAX_TIMES) { - LOG_ERROR("StepResultSet::GoToNextRow retrycount exceeded"); + LOG_ERROR("Step in busy ret is %{public}d", errCode); return E_STEP_RESULT_QUERY_EXCEEDED; } else { // Sleep to give the thread holding the lock a chance to finish @@ -206,7 +215,7 @@ int StepResultSet::GoToNextRow() FinishStep(); return E_STEP_RESULT_IS_AFTER_LAST; } else { - LOG_ERROR("StepResultSet::GoToNextRow step err = %{public}d", errCode); + LOG_ERROR("step ret is %{public}d", errCode); FinishStep(); return SQLiteError::ErrNo(errCode); } @@ -220,12 +229,10 @@ int StepResultSet::Close() isClosed = true; int errCode = FinishStep(); rdb = nullptr; - return errCode; -} -int StepResultSet::CheckSession() -{ - return E_OK; + connectionPool_->ReleaseConnection(connection_); + connection_ = nullptr; + return errCode; } /** @@ -234,6 +241,7 @@ int StepResultSet::CheckSession() int StepResultSet::PrepareStep() { if (isClosed) { + LOG_ERROR("resultSet closed"); return E_STEP_RESULT_CLOSED; } @@ -241,8 +249,13 @@ int StepResultSet::PrepareStep() return E_OK; } + if (connection_ == nullptr) { + LOG_ERROR("too many connections"); + return E_CON_OVER_LIMIT; + } + if (!SqliteDatabaseUtils::IsReadOnlySql(sql)) { - LOG_ERROR("StoreSession BeginStepQuery fail : not select sql !"); + LOG_ERROR("not a select sql!"); return E_EXECUTE_IN_STEP_QUERY; } @@ -250,6 +263,7 @@ int StepResultSet::PrepareStep() sqliteStatement = connection_->BeginStepQuery(errCode, sql, selectionArgs); if (sqliteStatement == nullptr) { connection_->EndStepQuery(); + LOG_ERROR("BeginStepQuery ret is %{public}d", errCode); return errCode; } @@ -261,22 +275,19 @@ int StepResultSet::PrepareStep() */ int StepResultSet::FinishStep() { - int errCode = CheckSession(); - if (errCode != E_OK) { - return errCode; - } - if (sqliteStatement == nullptr) { return E_OK; } sqliteStatement = nullptr; rowPos_ = INIT_POS; - if (connection_ != nullptr) { - errCode = connection_->EndStepQuery(); + if (connection_ == nullptr) { + return E_OK; } + + int errCode = connection_->EndStepQuery(); if (errCode != E_OK) { - LOG_ERROR("StepResultSet::FinishStep err = %d", errCode); + LOG_ERROR("ret is %d", errCode); } return errCode; } @@ -324,6 +335,7 @@ int StepResultSet::IsAtFirstRow(bool &result) const int StepResultSet::GetBlob(int columnIndex, std::vector &blob) { if (rowPos_ == INIT_POS) { + LOG_ERROR("query not executed."); return E_STEP_RESULT_QUERY_NOT_EXECUTED; } @@ -333,12 +345,13 @@ int StepResultSet::GetBlob(int columnIndex, std::vector &blob) int StepResultSet::GetString(int columnIndex, std::string &value) { if (rowPos_ == INIT_POS) { + LOG_ERROR("query not executed."); return E_STEP_RESULT_QUERY_NOT_EXECUTED; } int errCode = sqliteStatement->GetColumnString(columnIndex, value); if (errCode != E_OK) { - LOG_ERROR("StepResultSet::GetString is err=%{public}d", errCode); + LOG_ERROR("ret is %{public}d", errCode); return errCode; } return E_OK; @@ -347,12 +360,14 @@ int StepResultSet::GetString(int columnIndex, std::string &value) int StepResultSet::GetInt(int columnIndex, int &value) { if (rowPos_ == INIT_POS) { + LOG_ERROR("query not executed."); return E_STEP_RESULT_QUERY_NOT_EXECUTED; } int64_t columnValue; int errCode = sqliteStatement->GetColumnLong(columnIndex, columnValue); if (errCode != E_OK) { + LOG_ERROR("ret is %{public}d", errCode); return errCode; } value = static_cast(columnValue); @@ -362,10 +377,12 @@ int StepResultSet::GetInt(int columnIndex, int &value) int StepResultSet::GetLong(int columnIndex, int64_t &value) { if (rowPos_ == INIT_POS) { + LOG_ERROR("query not executed."); return E_STEP_RESULT_QUERY_NOT_EXECUTED; } int errCode = sqliteStatement->GetColumnLong(columnIndex, value); if (errCode != E_OK) { + LOG_ERROR("ret is %{public}d", errCode); return errCode; } return E_OK; @@ -374,10 +391,12 @@ int StepResultSet::GetLong(int columnIndex, int64_t &value) int StepResultSet::GetDouble(int columnIndex, double &value) { if (rowPos_ == INIT_POS) { + LOG_ERROR("query not executed."); return E_STEP_RESULT_QUERY_NOT_EXECUTED; } int errCode = sqliteStatement->GetColumnDouble(columnIndex, value); if (errCode != E_OK) { + LOG_ERROR("ret is %{public}d", errCode); return errCode; } return E_OK; @@ -388,6 +407,7 @@ int StepResultSet::IsColumnNull(int columnIndex, bool &isNull) ColumnType columnType; int errCode = GetColumnType(columnIndex, columnType); if (errCode != E_OK) { + LOG_ERROR("ret is %{public}d", errCode); return errCode; } isNull = (columnType == ColumnType::TYPE_NULL); diff --git a/relational_store/frameworks/native/rdb/src/store_session.cpp b/relational_store/frameworks/native/rdb/src/store_session.cpp deleted file mode 100644 index 312a822c..00000000 --- a/relational_store/frameworks/native/rdb/src/store_session.cpp +++ /dev/null @@ -1,447 +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. - */ - -#include "store_session.h" -#include -#include -#include -#include "logger.h" -#include "rdb_errno.h" -#if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) -#include "shared_block.h" -#endif -#include "sqlite_database_utils.h" -#include "sqlite_utils.h" -#include "base_transaction.h" - -namespace OHOS::NativeRdb { -StoreSession::StoreSession(SqliteConnectionPool &connectionPool) - : connectionPool(connectionPool), readConnection(nullptr), connection(nullptr), - readConnectionUseCount(0), connectionUseCount(0), isInStepQuery(false) -{ -} - -StoreSession::~StoreSession() -{ -} - -void StoreSession::AcquireConnection(bool isReadOnly) -{ - if (isReadOnly) { - if (readConnection == nullptr) { - readConnection = connectionPool.AcquireConnection(true); - } - readConnectionUseCount += 1; - return; - } - if (connection == nullptr) { - connection = connectionPool.AcquireConnection(false); - } - connectionUseCount += 1; - return; -} - -void StoreSession::ReleaseConnection(bool isReadOnly) -{ - if (isReadOnly) { - if ((readConnection == nullptr) || (readConnectionUseCount <= 0)) { - LOG_ERROR("SQLiteSession ReleaseConnection repeated release"); - return; - } - if (--readConnectionUseCount == 0) { - connectionPool.ReleaseConnection(readConnection); - readConnection = nullptr; - } - return; - } - if ((connection == nullptr) || (connectionUseCount <= 0)) { - LOG_ERROR("SQLiteSession ReleaseConnection repeated release"); - return; - } - - if (--connectionUseCount == 0) { - connectionPool.ReleaseConnection(connection); - connection = nullptr; - } -} - -int StoreSession::PrepareAndGetInfo( - const std::string &sql, bool &outIsReadOnly, int &numParameters, std::vector &columnNames) -{ - // Obtains the type of SQL statement. - int type = SqliteUtils::GetSqlStatementType(sql); - if (SqliteUtils::IsSpecial(type)) { - return E_TRANSACTION_IN_EXECUTE; - } - bool assumeReadOnly = SqliteUtils::IsSqlReadOnly(type); - AcquireConnection(assumeReadOnly); - auto con = assumeReadOnly ? readConnection : connection; - int errCode = con->PrepareAndGetInfo(sql, outIsReadOnly, numParameters, columnNames); - if (errCode != 0) { - ReleaseConnection(assumeReadOnly); - return errCode; - } - - ReleaseConnection(assumeReadOnly); - return E_OK; -} - -int StoreSession::BeginExecuteSql(const std::string &sql, bool &isReadOnly) -{ - int type = SqliteUtils::GetSqlStatementType(sql); - if (SqliteUtils::IsSpecial(type)) { - return E_TRANSACTION_IN_EXECUTE; - } - - bool assumeReadOnly = SqliteUtils::IsSqlReadOnly(type); - AcquireConnection(assumeReadOnly); - SqliteConnection *con = assumeReadOnly ? readConnection : connection; - int errCode = con->Prepare(sql, isReadOnly); - if (errCode != 0) { - ReleaseConnection(assumeReadOnly); - return errCode; - } - isReadOnly = assumeReadOnly; - return E_OK; -} -int StoreSession::ExecuteSql(const std::string &sql, const std::vector &bindArgs) -{ - bool isReadOnly = false; - int errCode = BeginExecuteSql(sql, isReadOnly); - if (errCode != 0) { - return errCode; - } - SqliteConnection *con = isReadOnly ? readConnection : connection; - errCode = con->ExecuteSql(sql, bindArgs); - ReleaseConnection(isReadOnly); - return errCode; -} - -int StoreSession::ExecuteForChangedRowCount( - int &changedRows, const std::string &sql, const std::vector &bindArgs) -{ - bool isReadOnly = false; - int errCode = BeginExecuteSql(sql, isReadOnly); - if (errCode != 0) { - return errCode; - } - auto con = isReadOnly ? readConnection : connection; - errCode = con->ExecuteForChangedRowCount(changedRows, sql, bindArgs); - ReleaseConnection(isReadOnly); - return errCode; -} - -int StoreSession::ExecuteForLastInsertedRowId( - int64_t &outRowId, const std::string &sql, const std::vector &bindArgs) -{ - bool isReadOnly = false; - int errCode = BeginExecuteSql(sql, isReadOnly); - if (errCode != 0) { - LOG_ERROR("rdbStore BeginExecuteSql failed"); - return errCode; - } - auto con = isReadOnly ? readConnection : connection; - errCode = con->ExecuteForLastInsertedRowId(outRowId, sql, bindArgs); - if (errCode != E_OK) { - LOG_ERROR("rdbStore ExecuteForLastInsertedRowId FAILED"); - } - ReleaseConnection(isReadOnly); - return errCode; -} - -int StoreSession::ExecuteGetLong(int64_t &outValue, const std::string &sql, const std::vector &bindArgs) -{ - bool isReadOnly = false; - int errCode = BeginExecuteSql(sql, isReadOnly); - if (errCode != 0) { - return errCode; - } - auto con = isReadOnly ? readConnection : connection; - errCode = con->ExecuteGetLong(outValue, sql, bindArgs); - ReleaseConnection(isReadOnly); - return errCode; -} - -int StoreSession::ExecuteGetString( - std::string &outValue, const std::string &sql, const std::vector &bindArgs) -{ - bool isReadOnly = false; - int errCode = BeginExecuteSql(sql, isReadOnly); - if (errCode != 0) { - return errCode; - } - auto con = isReadOnly ? readConnection : connection; - std::string sqlstr = sql; - int type = SqliteDatabaseUtils::GetSqlStatementType(sqlstr); - if (type == STATEMENT_PRAGMA) { - ReleaseConnection(isReadOnly); - AcquireConnection(false); - con = connection; - } - - errCode = con->ExecuteGetString(outValue, sql, bindArgs); - ReleaseConnection(isReadOnly); - return errCode; -} - -int StoreSession::Backup(const std::string databasePath, const std::vector destEncryptKey) -{ - std::vector bindArgs; - bindArgs.push_back(ValueObject(databasePath)); - if (destEncryptKey.size() != 0) { - bindArgs.push_back(ValueObject(destEncryptKey)); - } else { - std::string str = ""; - bindArgs.push_back(ValueObject(str)); - } - - int errCode = ExecuteSql(ATTACH_BACKUP_SQL, bindArgs); - if (errCode != E_OK) { - LOG_ERROR("ExecuteSql ATTACH_BACKUP_SQL error %{public}d", errCode); - return errCode; - } - int64_t count; - errCode = ExecuteGetLong(count, EXPORT_SQL, std::vector()); - if (errCode != E_OK) { - LOG_ERROR("ExecuteSql EXPORT_SQL error %{public}d", errCode); - return errCode; - } - - errCode = ExecuteSql(DETACH_BACKUP_SQL, std::vector()); - if (errCode != E_OK) { - LOG_ERROR("ExecuteSql DETACH_BACKUP_SQL error %{public}d", errCode); - return errCode; - } - return E_OK; -} - -// Checks whether this thread holds a database connection. -bool StoreSession::IsHoldingConnection() const -{ - if (connection == nullptr && readConnection == nullptr) { - return false; - } else { - return true; - } -} - -int StoreSession::CheckNoTransaction() const -{ - int errorCode = 0; - if (connectionPool.getTransactionStack().empty()) { - errorCode = E_STORE_SESSION_NO_CURRENT_TRANSACTION; - return errorCode; - } - return E_OK; -} - -int StoreSession::GiveConnectionTemporarily(int64_t milliseconds) -{ - int errorCode = CheckNoTransaction(); - if (errorCode != E_OK) { - return errorCode; - } - BaseTransaction transaction = connectionPool.getTransactionStack().top(); - if (transaction.IsMarkedSuccessful() || connectionPool.getTransactionStack().size() > 1) { - errorCode = E_STORE_SESSION_NOT_GIVE_CONNECTION_TEMPORARILY; - return errorCode; - } - - if (milliseconds > 0) { - std::this_thread::sleep_for(std::chrono::milliseconds(milliseconds)); - } - BeginTransaction(); - return E_OK; -} - -int StoreSession::Attach( - const std::string &alias, const std::string &pathName, const std::vector destEncryptKey) -{ - std::string journalMode; - int errCode = ExecuteGetString(journalMode, "PRAGMA journal_mode", std::vector()); - if (errCode != E_OK) { - LOG_ERROR("RdbStoreImpl CheckAttach fail to get journal mode : %{public}d", errCode); - return errCode; - } - journalMode = SqliteUtils::StrToUpper(journalMode); - if (journalMode == "WAL") { - LOG_ERROR("RdbStoreImpl attach is not supported in WAL mode"); - return E_NOT_SUPPORTED_ATTACH_IN_WAL_MODE; - } - - std::vector bindArgs; - bindArgs.push_back(ValueObject(pathName)); - bindArgs.push_back(ValueObject(alias)); - if (destEncryptKey.size() != 0) { - bindArgs.push_back(ValueObject(destEncryptKey)); - } else { - std::string str = ""; - bindArgs.push_back(ValueObject(str)); - } - errCode = ExecuteSql(ATTACH_SQL, bindArgs); - if (errCode != E_OK) { - LOG_ERROR("ExecuteSql ATTACH_SQL error %{public}d", errCode); - return errCode; - } - - return E_OK; -} - -int StoreSession::BeginTransaction(TransactionObserver *transactionObserver) -{ - if (connectionPool.getTransactionStack().empty()) { - AcquireConnection(false); - - int errCode = connection->ExecuteSql("BEGIN EXCLUSIVE;"); - if (errCode != E_OK) { - ReleaseConnection(false); - return errCode; - } - } - - if (transactionObserver != nullptr) { - transactionObserver->OnBegin(); - } - - BaseTransaction transaction(connectionPool.getTransactionStack().size()); - connectionPool.getTransactionStack().push(transaction); - - return E_OK; -} - -bool StoreSession::IsInTransaction() const -{ - return !connectionPool.getTransactionStack().empty(); -} - -std::shared_ptr StoreSession::BeginStepQuery( - int &errCode, const std::string &sql, const std::vector &selectionArgs) -{ - if (isInStepQuery == true) { - LOG_ERROR("StoreSession BeginStepQuery fail : begin more step query in one session !"); - errCode = E_MORE_STEP_QUERY_IN_ONE_SESSION; - return nullptr; // fail,already in - } - - if (SqliteUtils::GetSqlStatementType(sql) != SqliteUtils::STATEMENT_SELECT) { - LOG_ERROR("StoreSession BeginStepQuery fail : not select sql !"); - errCode = E_EXECUTE_IN_STEP_QUERY; - return nullptr; - } - - AcquireConnection(true); - std::shared_ptr statement = readConnection->BeginStepQuery(errCode, sql, selectionArgs); - if (statement == nullptr) { - ReleaseConnection(true); - return nullptr; - } - isInStepQuery = true; - return statement; -} - -int StoreSession::EndStepQuery() -{ - if (isInStepQuery == false) { - return E_OK; - } - - int errCode = readConnection->EndStepQuery(); - isInStepQuery = false; - ReleaseConnection(true); - return errCode; -} - -#if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) -int StoreSession::ExecuteForSharedBlock(int &rowNum, std::string sql, const std::vector &bindArgs, - AppDataFwk::SharedBlock *sharedBlock, int startPos, int requiredPos, bool isCountAllRows) -{ - bool isReadOnly = false; - int errCode = BeginExecuteSql(sql, isReadOnly); - if (errCode != E_OK) { - return errCode; - } - SqliteConnection *con = isReadOnly ? readConnection : connection; - errCode = - con->ExecuteForSharedBlock(rowNum, sql, bindArgs, sharedBlock, startPos, requiredPos, isCountAllRows); - ReleaseConnection(isReadOnly); - return errCode; -} -#endif - -int StoreSession::BeginTransaction() -{ - AcquireConnection(false); - - BaseTransaction transaction(connectionPool.getTransactionStack().size()); - int errCode = connection->ExecuteSql(transaction.GetTransactionStr()); - if (errCode != E_OK) { - LOG_DEBUG("storeSession BeginTransaction Failed"); - ReleaseConnection(false); - return errCode; - } - connectionPool.getTransactionStack().push(transaction); - ReleaseConnection(false); - return E_OK; -} - -int StoreSession::Commit() -{ - if (connectionPool.getTransactionStack().empty()) { - return E_OK; - } - BaseTransaction transaction = connectionPool.getTransactionStack().top(); - std::string sqlStr = transaction.GetCommitStr(); - if (sqlStr.size() <= 1) { - connectionPool.getTransactionStack().pop(); - return E_OK; - } - - AcquireConnection(false); - int errCode = connection->ExecuteSql(sqlStr); - ReleaseConnection(false); - if (errCode != E_OK) { - // if error the transaction is leaving for rollback - return errCode; - } - connectionPool.getTransactionStack().pop(); - return E_OK; -} - -int StoreSession::RollBack() -{ - std::stack transactionStack = connectionPool.getTransactionStack(); - if (transactionStack.empty()) { - return E_NO_TRANSACTION_IN_SESSION; - } - BaseTransaction transaction = transactionStack.top(); - transactionStack.pop(); - if (transaction.GetType() != TransType::ROLLBACK_SELF && !transactionStack.empty()) { - transactionStack.top().SetChildFailure(true); - } - AcquireConnection(false); - int errCode = connection->ExecuteSql(transaction.GetRollbackStr()); - ReleaseConnection(false); - if (errCode != E_OK) { - LOG_ERROR("storeSession RollBack Fail"); - } - - return errCode; -} - -int StoreSession::GetConnectionUseCount() -{ - return connectionUseCount; -} -} // namespace OHOS::NativeRdb diff --git a/relational_store/frameworks/native/rdb/src/value_object.cpp b/relational_store/frameworks/native/rdb/src/value_object.cpp index 5da15320..d288d127 100644 --- a/relational_store/frameworks/native/rdb/src/value_object.cpp +++ b/relational_store/frameworks/native/rdb/src/value_object.cpp @@ -24,24 +24,24 @@ ValueObject::ValueObject() { } -ValueObject::ValueObject(ValueObject::Type valueObject) noexcept : value(std::move(valueObject)) +ValueObject::ValueObject(ValueObject::Type val) noexcept : value(std::move(val)) { } -ValueObject::ValueObject(ValueObject &&valueObject) noexcept +ValueObject::ValueObject(ValueObject &&val) noexcept { - if (this == &valueObject) { + if (this == &val) { return; } - value = std::move(valueObject.value); + value = std::move(val.value); } -ValueObject::ValueObject(const ValueObject &valueObject) +ValueObject::ValueObject(const ValueObject &val) { - if (this == &valueObject) { + if (this == &val) { return; } - value = valueObject.value; + value = val.value; } ValueObject::~ValueObject() @@ -55,39 +55,50 @@ ValueObject::ValueObject(int val) : value(static_cast(val)) ValueObject::ValueObject(int64_t val) : value(val) { } -ValueObject::ValueObject(double val) + +ValueObject::ValueObject(double val) : value(val) { - value = val; } -ValueObject::ValueObject(bool val) + +ValueObject::ValueObject(bool val) : value(val) { - value = val; } -ValueObject::ValueObject(const std::string &val) + +ValueObject::ValueObject(const std::string &val) : value(val) { - value = val; } -ValueObject::ValueObject(const std::vector &val) + +ValueObject::ValueObject(const char *val) : ValueObject(std::string(val)) { - std::vector blob = val; - value = blob; } -ValueObject &ValueObject::operator=(ValueObject &&valueObject) noexcept +ValueObject::ValueObject(const std::vector &val) : value(val) { - if (this == &valueObject) { +} + +ValueObject::ValueObject(ValueObject::Asset val) : value(std::move(val)) +{ +} + +ValueObject::ValueObject(ValueObject::Assets val) : value(std::move(val)) +{ +} + +ValueObject &ValueObject::operator=(ValueObject &&val) noexcept +{ + if (this == &val) { return *this; } - value = std::move(valueObject.value); + value = std::move(val.value); return *this; } -ValueObject &ValueObject::operator=(const ValueObject &valueObject) +ValueObject &ValueObject::operator=(const ValueObject &val) { - if (this == &valueObject) { + if (this == &val) { return *this; } - value = valueObject.value; + value = val.value; return *this; } @@ -129,7 +140,18 @@ int ValueObject::GetBlob(std::vector &val) const return Get(val); } -template int ValueObject::Get(T &output) const +int ValueObject::GetAsset(Asset &val) const +{ + return Get(val); +} + +int ValueObject::GetAssets(Assets &val) const +{ + return Get(val); +} + +template +int ValueObject::Get(T &output) const { const T *v = std::get_if(&value); if (v == nullptr) { diff --git a/relational_store/frameworks/native/rdb/src/values_bucket.cpp b/relational_store/frameworks/native/rdb/src/values_bucket.cpp index e3f589ff..48864761 100644 --- a/relational_store/frameworks/native/rdb/src/values_bucket.cpp +++ b/relational_store/frameworks/native/rdb/src/values_bucket.cpp @@ -21,7 +21,7 @@ ValuesBucket::ValuesBucket() { } -ValuesBucket::ValuesBucket(std::map &valuesMap) : valuesMap(valuesMap) +ValuesBucket::ValuesBucket(std::map values) : values_(std::move(values)) { } @@ -31,63 +31,68 @@ ValuesBucket::~ValuesBucket() void ValuesBucket::PutString(const std::string &columnName, const std::string &value) { - valuesMap.insert(std::make_pair(columnName, ValueObject(value))); + values_.insert(std::make_pair(columnName, ValueObject(value))); } void ValuesBucket::PutInt(const std::string &columnName, int value) { - valuesMap.insert(std::make_pair(columnName, ValueObject(value))); + values_.insert(std::make_pair(columnName, ValueObject(value))); } void ValuesBucket::PutLong(const std::string &columnName, int64_t value) { - valuesMap.insert(std::make_pair(columnName, ValueObject(value))); + values_.insert(std::make_pair(columnName, ValueObject(value))); } void ValuesBucket::PutDouble(const std::string &columnName, double value) { - valuesMap.insert(std::make_pair(columnName, ValueObject(value))); + values_.insert(std::make_pair(columnName, ValueObject(value))); } void ValuesBucket::PutBool(const std::string &columnName, bool value) { - valuesMap.insert(std::make_pair(columnName, ValueObject(value))); + values_.insert(std::make_pair(columnName, ValueObject(value))); } void ValuesBucket::PutBlob(const std::string &columnName, const std::vector &value) { - valuesMap.insert(std::make_pair(columnName, ValueObject(value))); + values_.insert(std::make_pair(columnName, ValueObject(value))); } void ValuesBucket::PutNull(const std::string &columnName) { - valuesMap.insert(std::make_pair(columnName, ValueObject())); + values_.insert(std::make_pair(columnName, ValueObject())); +} + +void ValuesBucket::Put(const std::string &columnName, ValueObject value) +{ + values_.insert_or_assign(columnName, std::move(value)); } void ValuesBucket::Delete(const std::string &columnName) { - valuesMap.erase(columnName); + values_.erase(columnName); } void ValuesBucket::Clear() { - valuesMap.clear(); + values_.clear(); } int ValuesBucket::Size() const { - return valuesMap.size(); + return values_.size(); } bool ValuesBucket::IsEmpty() const { - return valuesMap.empty(); + return values_.empty(); } bool ValuesBucket::HasColumn(const std::string &columnName) const { - auto iter = valuesMap.find(columnName); - if (iter == valuesMap.end()) { + auto iter = values_.find(columnName); + if (iter == values_.end()) { return false; } return true; @@ -95,17 +100,17 @@ bool ValuesBucket::HasColumn(const std::string &columnName) const bool ValuesBucket::GetObject(const std::string &columnName, ValueObject &value) const { - auto iter = valuesMap.find(columnName); - if (iter == valuesMap.end()) { + auto iter = values_.find(columnName); + if (iter == values_.end()) { return false; } value = iter->second; return true; } -void ValuesBucket::GetAll(std::map &outValuesMap) const +std::map ValuesBucket::GetAll() const { - outValuesMap = valuesMap; + return values_; } } // namespace NativeRdb } // namespace OHOS diff --git a/relational_store/frameworks/native/rdb_data_ability_adapter/src/rdb_data_ability_utils.cpp b/relational_store/frameworks/native/rdb_data_ability_adapter/src/rdb_data_ability_utils.cpp index e1466be8..7cf48ca4 100644 --- a/relational_store/frameworks/native/rdb_data_ability_adapter/src/rdb_data_ability_utils.cpp +++ b/relational_store/frameworks/native/rdb_data_ability_adapter/src/rdb_data_ability_utils.cpp @@ -31,10 +31,10 @@ RdbDataAbilityUtils::~RdbDataAbilityUtils() DataShareValuesBucket RdbDataAbilityUtils::ToDataShareValuesBucket(const ValuesBucket &valuesBucket) { std::map values; - std::map valuesMap; - valuesBucket.GetAll(valuesMap); - for (auto &[key, value] : valuesMap) { - values.insert({key, value}); + for (auto &[key, value] : valuesBucket.values_) { + DataShareValueObject::Type dsValue; + ValueObject::Convert(value.value, dsValue); + values.insert(std::make_pair(key, dsValue)); } return DataShareValuesBucket(std::move(values)); } diff --git a/relational_store/frameworks/native/rdb_data_share_adapter/src/rdb_utils.cpp b/relational_store/frameworks/native/rdb_data_share_adapter/src/rdb_utils.cpp index c4b3602f..46fbe83e 100644 --- a/relational_store/frameworks/native/rdb_data_share_adapter/src/rdb_utils.cpp +++ b/relational_store/frameworks/native/rdb_data_share_adapter/src/rdb_utils.cpp @@ -26,9 +26,10 @@ constexpr RdbUtils::OperateHandler RdbUtils::HANDLERS[LAST_TYPE]; ValuesBucket RdbUtils::ToValuesBucket(const DataShareValuesBucket &valuesBucket) { std::map valuesMap; - auto values = valuesBucket.valuesMap; - for (auto &[key, value] : values) { - valuesMap.insert(std::pair(key, ValueObject(value))); + for (auto &[key, dsValue] : valuesBucket.valuesMap) { + ValueObject::Type value; + ValueObject::Convert(dsValue, value); + valuesMap.insert(std::pair(key, std::move(value))); } return ValuesBucket(valuesMap); } diff --git a/relational_store/frameworks/native/rdb_device_manager_adapter/include/rdb_device_manager_adapter.h b/relational_store/frameworks/native/rdb_device_manager_adapter/include/rdb_device_manager_adapter.h new file mode 100644 index 00000000..984d1193 --- /dev/null +++ b/relational_store/frameworks/native/rdb_device_manager_adapter/include/rdb_device_manager_adapter.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef RDB_DEVICE_MANAGER_ADAPTER_H +#define RDB_DEVICE_MANAGER_ADAPTER_H + +#include "device_manager.h" +#include "device_manager_callback.h" + +namespace OHOS { +namespace DeviceManagerAdaptor { +class RdbDeviceManagerAdaptor { +public: + static RdbDeviceManagerAdaptor &GetInstance(const std::string &packageName); + int GetEncryptedUuidByNetworkId(const std::string &networkId, std::string &uuid); + +private: + RdbDeviceManagerAdaptor(const std::string &packageName); + ~RdbDeviceManagerAdaptor(); + + void Init(); + void UnInit(); + + std::string packageName_; +}; + +class InitDeviceManagerCallback final : public DistributedHardware::DmInitCallback { +public: + InitDeviceManagerCallback() {}; + ~InitDeviceManagerCallback() {}; + void OnRemoteDied() override {}; +}; +} // namespace DeviceManagerAdaptor +} // namespace OHOS +#endif // RDB_DEVICE_MANAGER_ADAPTER_H diff --git a/relational_store/frameworks/native/rdb_device_manager_adapter/src/rdb_device_manager_adapter.cpp b/relational_store/frameworks/native/rdb_device_manager_adapter/src/rdb_device_manager_adapter.cpp new file mode 100644 index 00000000..5ec5f2d9 --- /dev/null +++ b/relational_store/frameworks/native/rdb_device_manager_adapter/src/rdb_device_manager_adapter.cpp @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "RdbDeviceManagerAdaptor" + +#include + +#include "rdb_device_manager_adapter.h" + +namespace OHOS { +namespace DeviceManagerAdaptor { +using namespace OHOS::DistributedHardware; +constexpr int32_t DM_OK = 0; +constexpr int32_t DM_ERROR = -1; +RdbDeviceManagerAdaptor::RdbDeviceManagerAdaptor(const std::string &packageName) + :packageName_(packageName) +{ + Init(); +} + +RdbDeviceManagerAdaptor::~RdbDeviceManagerAdaptor() +{ + UnInit(); +} + +RdbDeviceManagerAdaptor& RdbDeviceManagerAdaptor::GetInstance(const std::string &packageName) +{ + static RdbDeviceManagerAdaptor instance(packageName); + return instance; +} + +void RdbDeviceManagerAdaptor::Init() +{ + auto callback = std::make_shared(); + DeviceManager::GetInstance().InitDeviceManager(packageName_, callback); +} + +void RdbDeviceManagerAdaptor::UnInit() +{ + DeviceManager::GetInstance().UnInitDeviceManager(packageName_); +} + +int RdbDeviceManagerAdaptor::GetEncryptedUuidByNetworkId(const std::string &networkId, std::string &uuid) +{ + int ret = DeviceManager::GetInstance().GetEncryptedUuidByNetworkId(packageName_, networkId, uuid); + if (ret != DM_OK) { + return DM_ERROR; + } + return DM_OK; +} +} // namespace DeviceManagerAdaptor +} // namespace OHOS \ No newline at end of file diff --git a/relational_store/interfaces/inner_api/rdb/BUILD.gn b/relational_store/interfaces/inner_api/rdb/BUILD.gn index c5a0a05b..39b20a8b 100644 --- a/relational_store/interfaces/inner_api/rdb/BUILD.gn +++ b/relational_store/interfaces/inner_api/rdb/BUILD.gn @@ -29,8 +29,12 @@ config("native_rdb_config") { "include", "//base/security/huks/frameworks/huks_standard/main/common/include", "${relational_store_native_path}/rdb/include", + "${relational_store_native_path}/rdb_device_manager_adapter/include", "//utils/system/safwk/native/include", "//foundation/communication/ipc/interfaces/innerkits/ipc_core/include", + "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/include/", + "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/interfaces/include/", + "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/interfaces/include/relational", ] } @@ -104,7 +108,6 @@ base_sources = [ "${relational_store_native_path}/rdb/src/sqlite_statement.cpp", "${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/store_session.cpp", "${relational_store_native_path}/rdb/src/string_utils.cpp", "${relational_store_native_path}/rdb/src/value_object.cpp", "${relational_store_native_path}/rdb/src/values_bucket.cpp", @@ -159,6 +162,7 @@ ohos_shared_library("native_rdb") { "${relational_store_native_path}/rdb/src/share_block.cpp", "${relational_store_native_path}/rdb/src/shared_block_serializer_info.cpp", "${relational_store_native_path}/rdb/src/sqlite_shared_result_set.cpp", + "${relational_store_native_path}/rdb_device_manager_adapter/src/rdb_device_manager_adapter.cpp", ] public_deps = @@ -166,6 +170,7 @@ ohos_shared_library("native_rdb") { external_deps = [ "c_utils:utils", + "device_manager:devicemanagersdk", "hilog_native:libhilog", "hitrace_native:hitrace_meter", "huks:libhukssdk", @@ -221,6 +226,7 @@ ohos_static_library("native_rdb_static") { "${relational_store_native_path}/rdb/src/share_block.cpp", "${relational_store_native_path}/rdb/src/shared_block_serializer_info.cpp", "${relational_store_native_path}/rdb/src/sqlite_shared_result_set.cpp", + "${relational_store_native_path}/rdb_device_manager_adapter/src/rdb_device_manager_adapter.cpp", ] public_deps = @@ -228,6 +234,7 @@ ohos_static_library("native_rdb_static") { external_deps = [ "c_utils:utils", + "device_manager:devicemanagersdk", "hilog_native:libhilog", "hitrace_native:hitrace_meter", "huks:libhukssdk", diff --git a/relational_store/interfaces/inner_api/rdb/include/abs_rdb_predicates.h b/relational_store/interfaces/inner_api/rdb/include/abs_rdb_predicates.h index 9ec8ab63..6416708b 100644 --- a/relational_store/interfaces/inner_api/rdb/include/abs_rdb_predicates.h +++ b/relational_store/interfaces/inner_api/rdb/include/abs_rdb_predicates.h @@ -176,7 +176,7 @@ public: RDB_API_EXPORT virtual std::string GetJoinClause() const; /** - * @brief Sets the number of joins in the predicates. + * @brief Obtains the number of joins in the predicates. */ RDB_API_EXPORT virtual int GetJoinCount() const; diff --git a/relational_store/interfaces/inner_api/rdb/include/asset_value.h b/relational_store/interfaces/inner_api/rdb/include/asset_value.h new file mode 100644 index 00000000..ef01f45f --- /dev/null +++ b/relational_store/interfaces/inner_api/rdb/include/asset_value.h @@ -0,0 +1,28 @@ +/* + * 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 +namespace OHOS::NativeRdb { +struct AssetValue { + uint32_t version = 0; + std::string name; + std::string modifyTime; + std::string size; + std::string uri; +}; +} +#endif // OHOS_RELATIONAL_STORE_INNER_API_ASSET_VALUE_H diff --git a/relational_store/interfaces/inner_api/rdb/include/rdb_errno.h b/relational_store/interfaces/inner_api/rdb/include/rdb_errno.h index c3ca4d4c..7f89c41c 100644 --- a/relational_store/interfaces/inner_api/rdb/include/rdb_errno.h +++ b/relational_store/interfaces/inner_api/rdb/include/rdb_errno.h @@ -29,6 +29,11 @@ constexpr int E_OK = 0; */ constexpr int E_BASE = 14800000; +/** +* @brief The error when the capability not supported. +*/ +constexpr int E_NOT_SUPPORTED = 801; + /** * @brief The error code for common exceptions. */ @@ -258,6 +263,11 @@ constexpr int E_ARGS_READ_CON_OVERLOAD = (E_BASE + 46); * @brief The error when the wal file size over default limit. */ static constexpr int E_WAL_SIZE_OVER_LIMIT = (E_BASE + 47); + +/** +* @brief The error when the connection count is used up. +*/ +static constexpr int E_CON_OVER_LIMIT = (E_BASE + 48); } // namespace NativeRdb } // namespace OHOS diff --git a/relational_store/interfaces/inner_api/rdb/include/rdb_store.h b/relational_store/interfaces/inner_api/rdb/include/rdb_store.h index 72ab6599..d20fd736 100644 --- a/relational_store/interfaces/inner_api/rdb/include/rdb_store.h +++ b/relational_store/interfaces/inner_api/rdb/include/rdb_store.h @@ -27,6 +27,7 @@ #include "values_bucket.h" #include "rdb_types.h" #include "rdb_common.h" +#include "rdb_errno.h" namespace OHOS::NativeRdb { class RDB_API_EXPORT RdbStore { @@ -270,8 +271,8 @@ public: * @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 RemoteQuery(const std::string &device, - const AbsRdbPredicates &predicates, const std::vector &columns) = 0; + virtual std::shared_ptr RemoteQuery(const std::string &device, const AbsRdbPredicates &predicates, + const std::vector &columns, int &errCode) = 0; /** * @brief Updates data in the database based on a a specified instance object of AbsRdbPredicates. @@ -364,7 +365,7 @@ public: * * @param tables Indicates the tables name you want to set. */ - virtual bool SetDistributedTables(const std::vector& tables) = 0; + virtual int SetDistributedTables(const std::vector& tables) = 0; /** * @brief Obtain distributed table name of specified remote device according to local table name. @@ -374,7 +375,8 @@ public: * * @return Returns the distributed table name. */ - virtual std::string ObtainDistributedTableName(const std::string& device, const std::string& table) = 0; + virtual std::string ObtainDistributedTableName( + const std::string &device, const std::string &table, int &errCode) = 0; /** * @brief Sync data between devices. @@ -382,17 +384,17 @@ public: * @param device Indicates the remote device. * @param predicate Indicates the AbsRdbPredicates {@link AbsRdbPredicates} object. */ - virtual bool Sync(const SyncOption& option, const AbsRdbPredicates& predicate, const SyncCallback& callback) = 0; + virtual int Sync(const SyncOption& option, const AbsRdbPredicates& predicate, const SyncCallback& callback) = 0; /** * @brief Subscribe to event changes. */ - virtual bool Subscribe(const SubscribeOption& option, RdbStoreObserver *observer) = 0; + virtual int Subscribe(const SubscribeOption& option, RdbStoreObserver *observer) = 0; /** * @brief UnSubscribe to event changes. */ - virtual bool UnSubscribe(const SubscribeOption& option, RdbStoreObserver *observer) = 0; + virtual int UnSubscribe(const SubscribeOption& option, RdbStoreObserver *observer) = 0; /** * @brief Drop the specified devices Data. diff --git a/relational_store/interfaces/inner_api/rdb/include/rdb_store_config.h b/relational_store/interfaces/inner_api/rdb/include/rdb_store_config.h index 0e65d864..0d7e6709 100644 --- a/relational_store/interfaces/inner_api/rdb/include/rdb_store_config.h +++ b/relational_store/interfaces/inner_api/rdb/include/rdb_store_config.h @@ -417,7 +417,18 @@ public: */ RDB_API_EXPORT void SetReadConSize(int readConSize); + /** + * @brief Sets the encrypt key for the object. + */ + void SetEncryptKey(const std::vector &encryptKey); + + /** + * @brief Obtains the encrypt key in this {@code StoreConfig} object. + */ + std::vector GetEncryptKey() const; private: + void ClearEncryptKey(); + std::string name; std::string path; StorageMode storageMode; @@ -434,6 +445,7 @@ private: std::string moduleName_; bool isEncrypt_ = false; + std::vector encryptKey_{}; SecurityLevel securityLevel = SecurityLevel::LAST; std::string uri_; std::string readPermission_; diff --git a/relational_store/interfaces/inner_api/rdb/include/result_set.h b/relational_store/interfaces/inner_api/rdb/include/result_set.h index e4b2ace9..2a7f02a7 100644 --- a/relational_store/interfaces/inner_api/rdb/include/result_set.h +++ b/relational_store/interfaces/inner_api/rdb/include/result_set.h @@ -32,11 +32,11 @@ enum class ColumnType { TYPE_NULL = 0, /** Indicates the column type is INTEGER.*/ TYPE_INTEGER, - /** Indicates the column type is NULL.*/ - TYPE_FLOAT, /** Indicates the column type is FLOAT.*/ - TYPE_STRING, + TYPE_FLOAT, /** Indicates the column type is STRING.*/ + TYPE_STRING, + /** Indicates the column type is BLOB.*/ TYPE_BLOB, }; diff --git a/relational_store/interfaces/inner_api/rdb/include/value_object.h b/relational_store/interfaces/inner_api/rdb/include/value_object.h index e1ce57f4..ae4e7677 100644 --- a/relational_store/interfaces/inner_api/rdb/include/value_object.h +++ b/relational_store/interfaces/inner_api/rdb/include/value_object.h @@ -17,11 +17,12 @@ #define NATIVE_RDB_VALUE_OBJECT_H #include +#include #include #include -#include -#include "rdb_visibility.h" +#include "asset_value.h" +#include "rdb_visibility.h" namespace OHOS { namespace NativeRdb { /** @@ -40,19 +41,33 @@ enum class ValueObjectType { TYPE_BOOL, /** Indicates the ValueObject type is blob.*/ TYPE_BLOB, + /** Indicates the ValueObject type is asset.*/ + TYPE_ASSET, + /** Indicates the ValueObject type is assets.*/ + TYPE_ASSETS, }; /** * The ValueObject class of RDB. */ -class ValueObject { +class RDB_API_EXPORT ValueObject { public: /** * @brief Use Type replace std::variant. */ - using Type = std::variant>; + using Nil = std::monostate; + using Blob = std::vector; + using Asset = AssetValue; + using Assets = std::vector; + using Type = std::variant; Type value; + /** + * @brief convert a std::variant input to another std::variant output with different (..._Types) + */ + template + static bool Convert(const _T &input, std::variant<_Rest...> &output); + /** * @brief Constructor. */ @@ -68,17 +83,17 @@ public: * * A parameterized constructor used to create a ValueObject instance. */ - RDB_API_EXPORT ValueObject(Type valueObject) noexcept; + RDB_API_EXPORT ValueObject(Type val) noexcept; /** * @brief Move constructor. */ - RDB_API_EXPORT ValueObject(ValueObject &&valueObject) noexcept; + RDB_API_EXPORT ValueObject(ValueObject &&val) noexcept; /** * @brief Copy constructor. */ - RDB_API_EXPORT ValueObject(const ValueObject &valueObject); + RDB_API_EXPORT ValueObject(const ValueObject &val); /** * @brief Constructor. @@ -87,7 +102,7 @@ public: * * @param val Indicates an int input parameter. */ - RDB_API_EXPORT explicit ValueObject(int val); + RDB_API_EXPORT ValueObject(int32_t val); /** * @brief Constructor. @@ -96,7 +111,7 @@ public: * * @param val Indicates an int64_t input parameter. */ - RDB_API_EXPORT explicit ValueObject(int64_t val); + RDB_API_EXPORT ValueObject(int64_t val); /** * @brief Constructor. @@ -105,7 +120,7 @@ public: * * @param val Indicates an double input parameter. */ - RDB_API_EXPORT explicit ValueObject(double val); + RDB_API_EXPORT ValueObject(double val); /** * @brief Constructor. @@ -114,7 +129,7 @@ public: * * @param val Indicates an bool input parameter. */ - RDB_API_EXPORT explicit ValueObject(bool val); + RDB_API_EXPORT ValueObject(bool val); /** * @brief Constructor. @@ -123,7 +138,9 @@ public: * * @param val Indicates an string input parameter. */ - RDB_API_EXPORT explicit ValueObject(const std::string &val); + RDB_API_EXPORT ValueObject(const std::string &val); + + RDB_API_EXPORT ValueObject(const char *val); /** * @brief Constructor. @@ -132,7 +149,11 @@ public: * * @param val Indicates an vector input parameter. */ - RDB_API_EXPORT explicit ValueObject(const std::vector &blob); + RDB_API_EXPORT ValueObject(const std::vector &blob); + + RDB_API_EXPORT ValueObject(Asset val); + + RDB_API_EXPORT ValueObject(Assets val); /** * @brief Move assignment operator overloaded function. @@ -178,7 +199,14 @@ public: * @brief Obtains the vector value in this {@code ValueObject} object. */ RDB_API_EXPORT int GetBlob(std::vector &val) const; - + /** + * @brief Obtains the vector value in this {@code ValueObject} object. + */ + RDB_API_EXPORT int GetAsset(Asset &val) const; + /** + * @brief Obtains the vector value in this {@code ValueObject} object. + */ + RDB_API_EXPORT int GetAssets(Assets &val) const; /** * @brief Type conversion function. * @@ -234,11 +262,29 @@ public: * * @return Returns the vector type ValueObject. */ - operator std::vector () const + operator Blob () const { - return std::get>(value); + return std::get(value); } + /** + * @brief Type conversion function. + * + * @return Returns the vector type ValueObject. + */ + operator Asset () const + { + return std::get(value); + } + /** + * @brief Type conversion function. + * + * @return Returns the vector type ValueObject. + */ + operator Assets () const + { + return std::get(value); + } /** * @brief Type conversion function. * @@ -252,8 +298,59 @@ public: private: template int Get(T &output) const; + + template + struct index_of : std::integral_constant { + }; + + template + inline static constexpr size_t index_of_v = index_of<_Tp, _Types...>::value; + + template + struct index_of<_Tp, _First, _Rest...> + : std::integral_constant ? 0 : index_of_v<_Tp, _Rest...> + 1> { + }; + + template + static std::enable_if_t<(index_of_v<_T, _Rest...> < sizeof...(_Rest)), const _T *> GetIf( + const std::variant<_Rest...> &input) + { + return std::get_if<_T>(&input); + } + + template + static std::enable_if_t<(index_of_v<_T, _Rest...> >= sizeof...(_Rest)), const _T *> GetIf( + const std::variant<_Rest...> &input) + { + return nullptr; + } + + template + static bool Get(const _T &input, _O &output) + { + return false; + } + + template + static bool Get(const _T &input, _O &output); }; +template +bool ValueObject::Convert(const _T &input, std::variant<_Rest...> &output) +{ + return Get<_T, decltype(output), _Rest...>(input, output); +} + +template +bool ValueObject::Get(const _T &input, _O &output) +{ + const _First *val = GetIf<_First>(input); + if (val != nullptr) { + output = *val; + return true; + } + return Get<_T, _O, _Rest...>(input, output); +} } // namespace NativeRdb } // namespace OHOS #endif diff --git a/relational_store/interfaces/inner_api/rdb/include/values_bucket.h b/relational_store/interfaces/inner_api/rdb/include/values_bucket.h index 9d25d0de..261f7693 100644 --- a/relational_store/interfaces/inner_api/rdb/include/values_bucket.h +++ b/relational_store/interfaces/inner_api/rdb/include/values_bucket.h @@ -25,7 +25,7 @@ namespace NativeRdb { /** * The ValuesBucket class of RDB. */ -class ValuesBucket { +class RDB_API_EXPORT ValuesBucket { public: /** * @brief Constructor. @@ -37,7 +37,7 @@ public: * * A parameterized constructor used to create a ValuesBucket instance. */ - RDB_API_EXPORT explicit ValuesBucket(std::map &valuesMap); + RDB_API_EXPORT explicit ValuesBucket(std::map values); /** * @brief Destructor. @@ -99,6 +99,14 @@ public: */ RDB_API_EXPORT void PutNull(const std::string &columnName); + /** + * @brief Put the integer double bool string bytes asset asset and so on + * to this {@code ValuesBucket} object for the given column name. + * + * @param columnName Indicates the name of the column. + */ + RDB_API_EXPORT void Put(const std::string &columnName, ValueObject value); + /** * @brief Delete the ValueObject object for the given column name. * @@ -138,9 +146,9 @@ public: /** * @brief Obtains the ValuesBucket object's valuesmap. */ - RDB_API_EXPORT void GetAll(std::map &valuesMap) const; + RDB_API_EXPORT std::map GetAll() const; - std::map valuesMap; + std::map values_; }; } // namespace NativeRdb diff --git a/relational_store/interfaces/inner_api/rdb/mock/include/rdb_store_config.h b/relational_store/interfaces/inner_api/rdb/mock/include/rdb_store_config.h index aa3c7d56..64a3f566 100644 --- a/relational_store/interfaces/inner_api/rdb/mock/include/rdb_store_config.h +++ b/relational_store/interfaces/inner_api/rdb/mock/include/rdb_store_config.h @@ -132,7 +132,6 @@ private: StorageMode storageMode; std::string journalMode; std::string syncMode; - std::vector encryptKey; bool readOnly; std::string databaseFileType; @@ -141,6 +140,7 @@ private: std::string moduleName_; bool isEncrypt_ = false; + std::vector encryptKey_; SecurityLevel securityLevel = SecurityLevel::LAST; std::string uri_; std::string readPermission_; diff --git a/relational_store/test/js/dataability/unittest/src/DataAbilityPredicatesJsunit.test.js b/relational_store/test/js/dataability/unittest/src/DataAbilityPredicatesJsunit.test.js index 9b99b973..03ab110c 100644 --- a/relational_store/test/js/dataability/unittest/src/DataAbilityPredicatesJsunit.test.js +++ b/relational_store/test/js/dataability/unittest/src/DataAbilityPredicatesJsunit.test.js @@ -1916,25 +1916,6 @@ describe('dataAbilityPredicatesTest', function () { console.log(TAG + "************* testDataAbilityAnd0003 end *************"); }) - /** - * @tc.name predicates and normal test - * @tc.number SUB_DDM_AppDataFWK_JSRDB_DataAbilityPredicates_0153 - * @tc.desc predicates and normal test - */ - it('testDataAbilityAnd0004', 0, async function (done) { - console.log(TAG + "************* testDataAbilityAnd0004 start *************"); - { - let dataAbilityPredicates = await new dataAbility.DataAbilityPredicates(); - dataAbilityPredicates.equalTo("stringValue", "ABCDEFGHIJKLMN").or().or().equalTo("integerValue", 1); - let predicates = dataAbility.createRdbPredicates("AllDataType", dataAbilityPredicates); - - console.log(TAG + "you are starting a sql request with predicate or or," - + "using function or() immediately after another or(). that is ridiculous."); - } - done(); - console.log(TAG + "************* testDataAbilityAnd0004 end *************"); - }) - /** * @tc.name predicates order normal test * @tc.number SUB_DDM_AppDataFWK_JSRDB_DataAbilityPredicates_0160 diff --git a/relational_store/test/js/rdb/unittest/src/RdbstoreBackupRestoreWithFAContextJsunit.test.js b/relational_store/test/js/rdb/unittest/src/RdbstoreBackupRestoreWithFAContextJsunit.test.js deleted file mode 100644 index 4b174d56..00000000 --- a/relational_store/test/js/rdb/unittest/src/RdbstoreBackupRestoreWithFAContextJsunit.test.js +++ /dev/null @@ -1,245 +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. - */ -import {describe, beforeAll, beforeEach, afterEach, afterAll, it, expect} from 'deccjsunit/index' -import data_rdb from '@ohos.data.rdb' -import ability_featureAbility from '@ohos.ability.featureAbility' -import fileio from '@ohos.fileio' - -const TAG = "[RDB_JSKITS_TEST]" -const CREATE_TABLE_TEST = "CREATE TABLE IF NOT EXISTS test (" + "id INTEGER PRIMARY KEY AUTOINCREMENT, " - + "name TEXT NOT NULL, " + "age INTEGER, " + "salary REAL, " + "blobType BLOB)" -const DATABASE_DIR = "/data/storage/el2/database/entry/rdb/" -var rdbStore -var context -const STORE_CONFIG = { - name: "BackupResotreTest.db", -} -const DATABASE_BACKUP_NAME = "Backup.db" - -async function CreatRdbStore(context, STORE_CONFIG) { - let rdbStore = await data_rdb.getRdbStore(context, STORE_CONFIG, 1) - await rdbStore.executeSql(CREATE_TABLE_TEST, null) - let u8 = new Uint8Array([1, 2, 3]) - { - const valueBucket = { - "name": "zhangsan", - "age": 18, - "salary": 100.5, - "blobType": u8, - } - await rdbStore.insert("test", valueBucket) - } - { - const valueBucket = { - "name": "lisi", - "age": 28, - "salary": 100.5, - "blobType": u8, - } - await rdbStore.insert("test", valueBucket) - } - { - const valueBucket = { - "name": "wangwu", - "age": 38, - "salary": 90.0, - "blobType": u8, - } - await rdbStore.insert("test", valueBucket) - } - return rdbStore -} - -async function BackupTest(backupName) { - try { - let promiseRestore = rdbStore.backup(backupName) - promiseRestore.then(() => { - expect(false).assertTrue() - }).catch((err) => { - expect(true).assertTrue() - }) - await promiseRestore - } catch { - expect(true).assertTrue() - } - - rdbStore = null -} - -async function RestoreTest(restoreName) { - try { - let promiseRestore = rdbStore.restore(restoreName) - promiseRestore.then(() => { - expect(false).assertTrue() - }).catch((err) => { - expect(true).assertTrue() - }) - await promiseRestore - } catch { - expect(true).assertTrue() - } - - rdbStore = null -} - -describe('rdbStoreBackupRestoreWithFAContextTest', function () { - beforeAll(async function () { - console.info(TAG + 'beforeAll') - }) - - beforeEach(async function () { - console.info(TAG + 'beforeEach') - context = ability_featureAbility.getContext() - rdbStore = await CreatRdbStore(context, STORE_CONFIG) - }) - - afterEach(async function () { - console.info(TAG + 'afterEach') - rdbStore = null - await data_rdb.deleteRdbStore(context, STORE_CONFIG.name) - await data_rdb.deleteRdbStore(context, DATABASE_BACKUP_NAME) - }) - - afterAll(async function () { - console.info(TAG + 'afterAll') - }) - - console.log(TAG + "*************Unit Test Begin*************") - - /** - * @tc.name RDB Backup Restore test - * @tc.number SUB_DDM_RDB_JS_RdbBackupRestoreTest_0010 - * @tc.desc RDB backup and restore function test - */ - it('RdbBackupRestoreTest_0010', 0, async function (done) { - await console.log(TAG + "************* RdbBackupRestoreTest_0010 start *************") - - // RDB backup function test - let promiseBackup = rdbStore.backup(DATABASE_BACKUP_NAME) - promiseBackup.then(() => { - try { - fileio.accessSync(DATABASE_DIR + DATABASE_BACKUP_NAME) - fileio.accessSync(DATABASE_DIR + STORE_CONFIG.name) - } catch (err) { - expect(false).assertTrue() - } - }).catch((err) => { - expect(false).assertTrue() - }) - await promiseBackup - - // RDB restore function test - let promiseRestore = rdbStore.restore(DATABASE_BACKUP_NAME) - promiseRestore.then(() => { - try { - fileio.accessSync(DATABASE_DIR + DATABASE_BACKUP_NAME) - expect(false).assertTrue() - } catch (err) { - expect(true).assertTrue() - } - - try { - fileio.accessSync(DATABASE_DIR + STORE_CONFIG.name) - expect(true).assertTrue() - } catch (err) { - expect(false).assertTrue() - } - }).catch((err) => { - expect(false).assertTrue() - }) - await promiseRestore - - // RDB after restored, data query test - let predicates = new data_rdb.RdbPredicates("test") - predicates.equalTo("name", "zhangsan") - let resultSet = await rdbStore.query(predicates) - try { - console.log(TAG + "After restore resultSet query done") - expect(true).assertEqual(resultSet.goToFirstRow()) - const id = resultSet.getLong(resultSet.getColumnIndex("id")) - const name = resultSet.getString(resultSet.getColumnIndex("name")) - const blobType = resultSet.getBlob(resultSet.getColumnIndex("blobType")) - expect(1).assertEqual(id) - expect("zhangsan").assertEqual(name) - expect(1).assertEqual(blobType[0]) - } catch (err) { - expect(false).assertTrue() - } - resultSet.close() - resultSet = null - done() - await console.log(TAG + "************* RdbBackupRestoreTest_0010 end *************") - }) - - /** - * @tc.name RDB Backup test - * @tc.number SUB_DDM_RDB_JS_RdbBackupRestoreTest_0020 - * @tc.desc RDB backup function test - */ - it('RdbBackupRestoreTest_0020', 0, async function (done) { - await console.log(TAG + "************* RdbBackupRestoreTest_0020 start *************") - // RDB backup function test, backup file name empty - BackupTest("") - - // RDB backup function test, backup file name already exists - BackupTest(STORE_CONFIG.name) - - done() - await console.log(TAG + "************* RdbBackupRestoreTest_0020 end *************") - }) - - /** - * @tc.name RDB BackupRestore test - * @tc.number SUB_DDM_RDB_JS_RdbBackupRestoreTest_0030 - * @tc.desc RDB restore function test - */ - it('RdbBackupRestoreTest_0030', 0, async function (done) { - await console.log(TAG + "************* RdbBackupRestoreTest_0030 start *************") - await rdbStore.backup(DATABASE_BACKUP_NAME) - - // RDB restore function test, backup file name empty - RestoreTest("") - - // RDB restore function test, backup file is specified to database name - RestoreTest(STORE_CONFIG.name) - - done() - await console.log(TAG + "************* RdbBackupRestoreTest_0030 end *************") - }) - - /** - * @tc.name RDB BackupRestore test - * @tc.number SUB_DDM_RDB_JS_RdbBackupRestoreTest_0040 - * @tc.desc RDB restore function test - */ - it('RdbBackupRestoreTest_0040', 0, async function (done) { - await console.log(TAG + "************* RdbBackupRestoreTest_0040 start *************") - let dbName = "notExistName.db" - - // RDB restore function test, backup file does not exists - try { - fileio.accessSync(DATABASE_DIR + dbName) - expect(false).assertTrue() - } catch { - RestoreTest(dbName) - } - - done() - await console.log(TAG + "************* RdbBackupRestoreTest_0040 end *************") - }) - - console.log(TAG + "*************Unit Test End*************") - } -) diff --git a/relational_store/test/js/rdb/unittest/src/RdbstorePredicatesJsunit.test.js b/relational_store/test/js/rdb/unittest/src/RdbstorePredicatesJsunit.test.js index 602f8c12..0d22de23 100644 --- a/relational_store/test/js/rdb/unittest/src/RdbstorePredicatesJsunit.test.js +++ b/relational_store/test/js/rdb/unittest/src/RdbstorePredicatesJsunit.test.js @@ -1798,23 +1798,6 @@ describe('rdbPredicatesTest', function () { console.log(TAG + "************* testAnd0003 end *************"); }) - /** - * @tc.name predicates and normal test - * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0153 - * @tc.desc predicates and normal test - */ - it('testAnd0004', 0, async function (done) { - console.log(TAG + "************* testAnd0004 start *************"); - - let predicates = new dataRdb.RdbPredicates("AllDataType"); - predicates.equalTo("stringValue", "ABCDEFGHIJKLMN").or().or().equalTo("integerValue", 1); - console.log(TAG + "you are starting a sql request with predicate or or," - + "using function or() immediately after another or(). that is ridiculous."); - - done(); - console.log(TAG + "************* testAnd0004 end *************"); - }) - /** * @tc.name predicates order normal test * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0160 diff --git a/relational_store/test/js/relationalstore/performance/src/RdbStoreOthersCallbackPerf.js b/relational_store/test/js/relationalstore/performance/src/RdbStoreOthersCallbackPerf.js index 6fa5cec9..77e7cb07 100644 --- a/relational_store/test/js/relationalstore/performance/src/RdbStoreOthersCallbackPerf.js +++ b/relational_store/test/js/relationalstore/performance/src/RdbStoreOthersCallbackPerf.js @@ -162,48 +162,4 @@ describe('rdbStoreOthersCallbackPerf', function () { let startTime = new Date().getTime(); executeSqlCallbackPerf(0); }) - - it('SUB_DDM_PERF_RDB_backup_Callback_001', 0, async function (done) { - let averageTime = 0; - - async function backupCallbackPerf(index) { - rdbStore.backup("backup.db", function (err, data) { - if (index < BASE_COUNT) { - backupCallbackPerf(index + 1); - } else { - let endTime = new Date().getTime(); - averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; - console.info(TAG + " the backup_Callback average time is: " + averageTime + " μs"); - expect(averageTime < BASE_LINE).assertTrue(); - done(); - } - }) - } - - let startTime = new Date().getTime(); - backupCallbackPerf(0); - }) - - it('SUB_DDM_PERF_RDB_restore_Callback_001', 0, async function (done) { - let averageTime = 0; - - async function restoreCallbackPerf(index) { - rdbStore.restore("backup.db", function (err, data) { - if (index < BASE_COUNT) { - restoreCallbackPerf(index + 1); - } else { - let endTime = new Date().getTime(); - averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; - console.info(TAG + " the restore_Callback average time is: " + averageTime + " μs"); - expect(averageTime < BASE_LINE).assertTrue(); - dataRdb.deleteRdbStore(context, "backup.db", function (err, data) { - done(); - }) - } - }) - } - - let startTime = new Date().getTime(); - restoreCallbackPerf(0); - }) }) diff --git a/relational_store/test/js/relationalstore/unittest/src/RdbStoreDistributedJsunit.test.js b/relational_store/test/js/relationalstore/unittest/src/RdbStoreDistributedJsunit.test.js index d4957a29..ff5326f6 100644 --- a/relational_store/test/js/relationalstore/unittest/src/RdbStoreDistributedJsunit.test.js +++ b/relational_store/test/js/relationalstore/unittest/src/RdbStoreDistributedJsunit.test.js @@ -19,6 +19,7 @@ import ability_featureAbility from '@ohos.ability.featureAbility' const TAG = "[RELATIONAL_STORE_JSKITS_TEST]" const STORE_NAME = "distributed_rdb.db" +const E_NOT_SUPPORTED = 801; var rdbStore = undefined; var context = ability_featureAbility.getContext() @@ -94,8 +95,8 @@ describe('rdbStoreDistributedTest', function () { console.log(TAG + "set none to be distributed table success"); expect(rdbStore).assertEqual(rdbStore) } catch (err) { - console.log(TAG + "set none to be distributed table failed"); - expect(null).assertFail(); + console.log(TAG + `set none to be distributed table failed, err is ${err.code}.`); + expect(E_NOT_SUPPORTED).assertEqual(err.code); } done() console.log(TAG + "************* testRdbStoreDistributed002 end *************"); @@ -113,8 +114,8 @@ describe('rdbStoreDistributedTest', function () { console.log(TAG + "set employee to be distributed table success"); expect(rdbStore).assertEqual(rdbStore) } catch (err) { - console.log(TAG + "set employee to be distributed table failed"); - expect(null).assertFail(); + console.log(TAG + `set employee to be distributed table failed, err is ${err.code}.`); + expect(E_NOT_SUPPORTED).assertEqual(err.code); } done() console.log(TAG + "************* testRdbStoreDistributed003 end *************"); @@ -132,8 +133,8 @@ describe('rdbStoreDistributedTest', function () { console.log(TAG + "set employee and product to be distributed table success"); expect(rdbStore).assertEqual(rdbStore) } catch (err) { - console.log(TAG + "set employee and product to be distributed table failed"); - expect(null).assertFail(); + console.log(TAG + `set employee and product to be distributed table failed, err is ${err.code}.`); + expect(E_NOT_SUPPORTED).assertEqual(err.code); } done() console.log(TAG + "************* testRdbStoreDistributed004 end *************"); diff --git a/relational_store/test/js/relationalstore/unittest/src/RdbstorePredicatesJsunit.test.js b/relational_store/test/js/relationalstore/unittest/src/RdbstorePredicatesJsunit.test.js index bfcd076b..d990822b 100644 --- a/relational_store/test/js/relationalstore/unittest/src/RdbstorePredicatesJsunit.test.js +++ b/relational_store/test/js/relationalstore/unittest/src/RdbstorePredicatesJsunit.test.js @@ -1802,23 +1802,6 @@ describe('rdbPredicatesTest', function () { console.log(TAG + "************* testAnd0003 end *************"); }) - /** - * @tc.name predicates and normal test - * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0153 - * @tc.desc predicates and normal test - */ - it('testAnd0004', 0, async function (done) { - console.log(TAG + "************* testAnd0004 start *************"); - - let predicates = new data_relationalStore.RdbPredicates("AllDataType"); - predicates.equalTo("stringValue", "ABCDEFGHIJKLMN").or().or().equalTo("integerValue", 1); - console.log(TAG + "you are starting a sql request with predicate or or," - + "using function or() immediately after another or(). that is ridiculous."); - - done(); - console.log(TAG + "************* testAnd0004 end *************"); - }) - /** * @tc.name predicates order normal test * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0160 diff --git a/relational_store/test/native/rdb/BUILD.gn b/relational_store/test/native/rdb/BUILD.gn index e340d52a..3bed308b 100644 --- a/relational_store/test/native/rdb/BUILD.gn +++ b/relational_store/test/native/rdb/BUILD.gn @@ -56,6 +56,7 @@ ohos_unittest("NativeRdbTest") { "unittest/rdb_store_concurrent_test.cpp", "unittest/rdb_store_config_test.cpp", "unittest/rdb_store_interface_test.cpp", + "unittest/rdb_store_rekey_test.cpp", "unittest/rdb_transaction_test.cpp", "unittest/rdb_update_test.cpp", "unittest/rdb_upgrade_test.cpp", diff --git a/relational_store/test/native/rdb/distributedtest/rdb_store_impl_test/distributed_test.cpp b/relational_store/test/native/rdb/distributedtest/rdb_store_impl_test/distributed_test.cpp index 8c5204d9..3482e061 100644 --- a/relational_store/test/native/rdb/distributedtest/rdb_store_impl_test/distributed_test.cpp +++ b/relational_store/test/native/rdb/distributedtest/rdb_store_impl_test/distributed_test.cpp @@ -152,12 +152,14 @@ HWTEST_F(DistributedTest, RemoteQuery001, TestSize.Level1) }); std::vector tables = {"test"}; DeviceManager::GetInstance().GetTrustedDeviceList(PKG_NAME, "", deviceInfos_); - std::string test = store_->ObtainDistributedTableName(deviceInfos_[0].networkId, tables[0]); + int errCode = E_ERROR; + std::string test = store_->ObtainDistributedTableName(deviceInfos_[0].networkId, tables[0], errCode); AbsRdbPredicates predicate(tables[0]); predicate.EqualTo("name", "zhangsan"); std::vector columns; - std::shared_ptr resultSet = store_-> RemoteQuery(deviceInfos_[0].networkId, predicate, columns); - + errCode = E_ERROR; + std::shared_ptr resultSet = store_->RemoteQuery(deviceInfos_[0].networkId, predicate, columns, errCode); + EXPECT_TRUE(ret > 0); EXPECT_EQ(returvalue, "zhangsan"); } diff --git a/relational_store/test/native/rdb/unittest/rdb_encrypt_decrypt_test.cpp b/relational_store/test/native/rdb/unittest/rdb_encrypt_decrypt_test.cpp index 29d28ac0..44689a2c 100644 --- a/relational_store/test/native/rdb/unittest/rdb_encrypt_decrypt_test.cpp +++ b/relational_store/test/native/rdb/unittest/rdb_encrypt_decrypt_test.cpp @@ -245,25 +245,33 @@ HWTEST_F(RdbEncryptTest, RdbStore_Encrypt_05, TestSize.Level1) /** * @tc.name: RdbStore_Encrypt_Decrypt_Test_006 - * @tc.desc: test SaveSecretKeyToFile when KeyFileType isNot PUB_KEY_FILE + * @tc.desc: test GetRdbStore with specified key * @tc.type: FUNC */ HWTEST_F(RdbEncryptTest, RdbStore_Encrypt_06, TestSize.Level1) { + std::vector key{ 1, 2, 3 }; RdbStoreConfig config(RdbEncryptTest::ENCRYPTED_DATABASE_NAME); - config.SetEncryptStatus(true); - config.SetBundleName("com.example.TestEncrypt6"); + config.SetEncryptKey(key); EncryptTestOpenCallback helper; int errCode; std::shared_ptr store = RdbHelper::GetRdbStore(config, 1, helper, errCode); EXPECT_NE(store, nullptr); - bool ret = - RdbSecurityManager::GetInstance().CheckKeyDataFileExists(RdbSecurityManager::KeyFileType::PUB_KEY_BAK_FILE); - EXPECT_EQ(ret, false); - std::vector key = RdbSecurityManager::GetInstance().GenerateRandomNum(RdbSecurityManager::RDB_KEY_SIZE); - bool flag = RdbSecurityManager::GetInstance().SaveSecretKeyToFile( - RdbSecurityManager::KeyFileType::PUB_KEY_BAK_FILE, key); - EXPECT_EQ(flag, true); + + std::string keyPath = RDB_TEST_PATH + "key/" + "encrypted.pub_key"; + std::string newKeyPath = RDB_TEST_PATH + "key/" + +"encrypted.pub_key.new"; + bool isFileExists = OHOS::FileExists(keyPath); + EXPECT_EQ(isFileExists, false); + isFileExists = OHOS::FileExists(newKeyPath); + EXPECT_EQ(isFileExists, false); + + store.reset(); + RdbHelper::ClearCache(); + + std::vector wrongKey{ 4, 5, 6 }; + config.SetEncryptKey(wrongKey); + store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_EQ(store, nullptr); } /** @@ -280,9 +288,9 @@ HWTEST_F(RdbEncryptTest, RdbStore_Encrypt_07, TestSize.Level1) int errCode; std::shared_ptr store = RdbHelper::GetRdbStore(config, 1, helper, errCode); EXPECT_NE(store, nullptr); - auto key = RdbSecurityManager::GetInstance().GetRdbPassword(RdbSecurityManager::KeyFileType::PUB_KEY_BAK_FILE); + auto key = RdbSecurityManager::GetInstance().GetRdbPassword(RdbSecurityManager::KeyFileType::PUB_KEY_FILE_NEW_KEY); RdbPassword password = {}; - EXPECT_EQ(key, password); + EXPECT_NE(key, password); } /** @@ -301,6 +309,9 @@ HWTEST_F(RdbEncryptTest, RdbStore_Encrypt_08, TestSize.Level1) int errCode; std::shared_ptr store = RdbHelper::GetRdbStore(config, 1, helper, errCode); EXPECT_NE(store, nullptr); + + errCode = RdbHelper::DeleteRdbStore(path); + EXPECT_EQ(errCode, E_OK); } /** @@ -324,7 +335,7 @@ HWTEST_F(RdbEncryptTest, RdbStore_Encrypt_09, TestSize.Level1) EXPECT_EQ(ret, E_OK); EXPECT_EQ(distributedStatus, false); ret = RdbSecurityManager::GetInstance().GetKeyDistributedStatus( - RdbSecurityManager::KeyFileType::PUB_KEY_BAK_FILE, distributedStatus); + RdbSecurityManager::KeyFileType::PUB_KEY_FILE_NEW_KEY, distributedStatus); EXPECT_EQ(ret, E_ERROR); EXPECT_EQ(distributedStatus, false); ret = RdbSecurityManager::GetInstance().SetKeyDistributedStatus( @@ -335,6 +346,6 @@ HWTEST_F(RdbEncryptTest, RdbStore_Encrypt_09, TestSize.Level1) EXPECT_EQ(ret, E_OK); EXPECT_EQ(distributedStatus, true); ret = RdbSecurityManager::GetInstance().SetKeyDistributedStatus( - RdbSecurityManager::KeyFileType::PUB_KEY_BAK_FILE, distributedStatus); + RdbSecurityManager::KeyFileType::PUB_KEY_FILE_NEW_KEY, distributedStatus); EXPECT_EQ(ret, E_ERROR); } diff --git a/relational_store/test/native/rdb/unittest/rdb_predicates_test.cpp b/relational_store/test/native/rdb/unittest/rdb_predicates_test.cpp index 4d055a38..c9378919 100644 --- a/relational_store/test/native/rdb/unittest/rdb_predicates_test.cpp +++ b/relational_store/test/native/rdb/unittest/rdb_predicates_test.cpp @@ -1600,4 +1600,22 @@ HWTEST_F(RdbStorePredicateTest, RdbStore_InDevices_InAllDevices_026, TestSize.Le AbsRdbPredicates* absRdbPredicates1 = predicates.InAllDevices(); EXPECT_NE(absRdbPredicates1, nullptr); EXPECT_EQ(absRdbPredicates, absRdbPredicates1); +} + +/* * + * @tc.name: RdbStore_GetDistributedPredicates_027 + * @tc.desc: Normal testCase of RdbPredicates for GetDistributedPredicates method + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(RdbStorePredicateTest, RdbStore_GetDistributedPredicates_027, TestSize.Level1) +{ + RdbPredicates predicates("AllDataType"); + predicates.EqualTo("stringValue", "ABCDEFGHIJKLMN")->OrderByDesc("integerValue")->Limit(2); + auto distributedRdbPredicates = predicates.GetDistributedPredicates(); + EXPECT_EQ(distributedRdbPredicates.table_, "AllDataType"); + EXPECT_EQ(distributedRdbPredicates.operations_.size(), 3UL); + EXPECT_EQ(distributedRdbPredicates.operations_[0].operator_, OHOS::DistributedRdb::EQUAL_TO); + EXPECT_EQ(distributedRdbPredicates.operations_[0].field_, "stringValue"); + EXPECT_EQ(distributedRdbPredicates.operations_[0].values_[0], "ABCDEFGHIJKLMN"); } \ No newline at end of file diff --git a/relational_store/test/native/rdb/unittest/rdb_store_config_test.cpp b/relational_store/test/native/rdb/unittest/rdb_store_config_test.cpp index 74d88c16..8c41c97c 100644 --- a/relational_store/test/native/rdb/unittest/rdb_store_config_test.cpp +++ b/relational_store/test/native/rdb/unittest/rdb_store_config_test.cpp @@ -73,6 +73,7 @@ void RdbStoreConfigTest::SetUp(void) void RdbStoreConfigTest::TearDown(void) { + RdbHelper::DeleteRdbStore(RDB_TEST_PATH + "config_test.db"); RdbHelper::ClearCache(); } @@ -247,7 +248,7 @@ HWTEST_F(RdbStoreConfigTest, RdbStoreConfig_006, TestSize.Level1) std::string currentMode; int ret = store->ExecuteAndGetString(currentMode, "PRAGMA journal_mode"); EXPECT_EQ(ret, E_OK); - EXPECT_EQ(currentMode, "wal"); + EXPECT_EQ(currentMode, "delete"); } /** @@ -756,7 +757,7 @@ HWTEST_F(RdbStoreConfigTest, RdbStoreConfig_025, TestSize.Level1) retEncryptAlgo = config.GetEncryptAlgo(); EXPECT_EQ("", retEncryptAlgo); store = RdbHelper::GetRdbStore(config, 1, helper, errCode); - EXPECT_EQ(store, nullptr); + EXPECT_NE(store, nullptr); } /** diff --git a/relational_store/test/native/rdb/unittest/rdb_store_rekey_test.cpp b/relational_store/test/native/rdb/unittest/rdb_store_rekey_test.cpp new file mode 100644 index 00000000..cca265c4 --- /dev/null +++ b/relational_store/test/native/rdb/unittest/rdb_store_rekey_test.cpp @@ -0,0 +1,289 @@ +/* +* 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. +*/ + +#include +#include +#include + +#include "common.h" +#include "file_ex.h" +#include "rdb_errno.h" +#include "rdb_helper.h" +#include "rdb_open_callback.h" +#include "rdb_security_manager.h" +#include "sqlite_database_utils.h" + +using namespace testing::ext; +using namespace OHOS::NativeRdb; +class RdbRekeyTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp() override; + void TearDown() override; + + static std::string RemoveSuffix(const std::string &name); + std::chrono::system_clock::time_point GetKeyFileDate(const std::string &dbName); + bool ChangeKeyFileDate(const std::string &dbName, int rep); + RdbStoreConfig GetRdbConfig(const std::string &name); + void InsertData(std::shared_ptr &store); + void CheckQueryData(std::shared_ptr &store); + + static const std::string encryptedDatabaseName; + static const std::string encryptedDatabasePath; + static const std::string encryptedDatabaseKeyDir; + static const std::string encryptedDatabaseMockName; + static const std::string encryptedDatabaseMockPath; + static constexpr int HOURS_EXPIRED = (24 * 365) + 1; + static constexpr int HOURS_NOT_EXPIRED = (24 * 30); +}; + +const std::string RdbRekeyTest::encryptedDatabaseName = "encrypted.db"; +const std::string RdbRekeyTest::encryptedDatabasePath = RDB_TEST_PATH + encryptedDatabaseName; +const std::string RdbRekeyTest::encryptedDatabaseKeyDir = RDB_TEST_PATH + "key/"; +const std::string RdbRekeyTest::encryptedDatabaseMockName = "encrypted_mock.db"; +const std::string RdbRekeyTest::encryptedDatabaseMockPath = RDB_TEST_PATH + encryptedDatabaseMockName; + +class RekeyTestOpenCallback : public RdbOpenCallback { +public: + int OnCreate(RdbStore &store) override; + int OnUpgrade(RdbStore &store, int oldVersion, int newVersion) override; + static const std::string createTableTest; +}; + +std::string const RekeyTestOpenCallback::createTableTest = "CREATE TABLE IF NOT EXISTS test " + "(id INTEGER PRIMARY KEY " + "AUTOINCREMENT, " + "name TEXT NOT NULL, age INTEGER, " + "salary " + "REAL, blobType BLOB)"; + +int RekeyTestOpenCallback::OnCreate(RdbStore &store) +{ + return store.ExecuteSql(createTableTest); +} + +int RekeyTestOpenCallback::OnUpgrade(RdbStore &store, int oldVersion, int newVersion) +{ + return E_OK; +} + +void RdbRekeyTest::SetUpTestCase() {} + +void RdbRekeyTest::TearDownTestCase() {} + +void RdbRekeyTest::SetUp() +{ + RdbStoreConfig config = GetRdbConfig(encryptedDatabasePath); + RekeyTestOpenCallback helper; + int errCode; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_NE(store, nullptr); + InsertData(store); + store.reset(); + RdbHelper::ClearCache(); +} + +void RdbRekeyTest::TearDown() +{ + RdbHelper::ClearCache(); + RdbHelper::DeleteRdbStore(RdbRekeyTest::encryptedDatabasePath); +} + +std::string RdbRekeyTest::RemoveSuffix(const string &name) +{ + std::string suffix(".db"); + auto pos = name.rfind(suffix); + if (pos == std::string::npos || pos < name.length() - suffix.length()) { + return name; + } + return { name, 0, pos }; +} + +std::chrono::system_clock::time_point RdbRekeyTest::GetKeyFileDate(const std::string &dbName) +{ + std::chrono::system_clock::time_point timePoint; + std::string name = RemoveSuffix(dbName); + auto keyPath = RDB_TEST_PATH + "key/" + name + ".pub_key"; + if (!OHOS::FileExists(keyPath)) { + return timePoint; + } + std::vector content; + auto loaded = OHOS::LoadBufferFromFile(keyPath, content); + if (!loaded) { + return timePoint; + } + auto iter = content.begin(); + iter++; + constexpr uint32_t dateFileLength = sizeof(time_t) / sizeof(uint8_t); + std::vector date; + date.assign(iter, iter + dateFileLength); + timePoint = std::chrono::system_clock::from_time_t(*reinterpret_cast(const_cast(&date[0]))); + return timePoint; +} + +bool RdbRekeyTest::ChangeKeyFileDate(const std::string &dbName, int rep) +{ + std::string name = RemoveSuffix(dbName); + auto keyPath = RDB_TEST_PATH + "key/" + name + ".pub_key"; + if (!OHOS::FileExists(keyPath)) { + return false; + } + std::vector content; + auto loaded = OHOS::LoadBufferFromFile(keyPath, content); + if (!loaded) { + return false; + } + auto time = + std::chrono::system_clock::to_time_t(std::chrono::system_clock::system_clock::now() - std::chrono::hours(rep)); + std::vector date(reinterpret_cast(&time), reinterpret_cast(&time) + sizeof(time)); + std::copy(date.begin(), date.end(), ++content.begin()); + + auto saved = OHOS::SaveBufferToFile(keyPath, content); + return saved; +} + +RdbStoreConfig RdbRekeyTest::GetRdbConfig(const std::string &name) +{ + RdbStoreConfig config(name); + config.SetEncryptStatus(true); + config.SetBundleName("com.example.test_rekey"); + return config; +} + +void RdbRekeyTest::InsertData(std::shared_ptr &store) +{ + int64_t id; + ValuesBucket values; + std::string name = "zhangsan"; + int age = 18; + double salary = 100.5; + std::vector blob{ 1, 2, 3 }; + values.PutString("name", name); + values.PutInt("age", age); + values.PutDouble("salary", salary); + values.PutBlob("blobType", blob); + int insertRet = store->Insert(id, "test", values); + EXPECT_EQ(insertRet, E_OK); +} + +void RdbRekeyTest::CheckQueryData(std::shared_ptr &store) +{ + std::unique_ptr resultSet = + store->QuerySql("SELECT * FROM test WHERE name = ?", std::vector{ "zhangsan" }); + EXPECT_NE(resultSet, nullptr); + int result = resultSet->GoToFirstRow(); + EXPECT_EQ(result, E_OK); + int columnIndex; + std::string strVal; + ColumnType columnType; + result = resultSet->GetColumnIndex("name", columnIndex); + EXPECT_EQ(result, E_OK); + result = resultSet->GetColumnType(columnIndex, columnType); + EXPECT_EQ(result, E_OK); + EXPECT_EQ(columnType, ColumnType::TYPE_STRING); + result = resultSet->GetString(columnIndex, strVal); + EXPECT_EQ(result, E_OK); + EXPECT_EQ("zhangsan", strVal); + + result = resultSet->Close(); + EXPECT_EQ(result, E_OK); +} + +/** +* @tc.name: Rdb_Rekey_Test_001 +* @tc.desc: test RdbStore rekey function +* @tc.type: FUNC +*/ +HWTEST_F(RdbRekeyTest, Rdb_Rekey_01, TestSize.Level1) +{ + std::string keyPath = encryptedDatabaseKeyDir + RemoveSuffix(encryptedDatabaseName) + ".pub_key"; + std::string newKeyPath = encryptedDatabaseKeyDir + RemoveSuffix(encryptedDatabaseName) + ".pub_key.new"; + + bool isFileExists = OHOS::FileExists(keyPath); + ASSERT_TRUE(isFileExists); + + bool isFileDateChanged = ChangeKeyFileDate(encryptedDatabaseName, RdbRekeyTest::HOURS_EXPIRED); + ASSERT_TRUE(isFileDateChanged); + + auto changedDate = GetKeyFileDate(encryptedDatabaseName); + ASSERT_TRUE(std::chrono::system_clock::now() - changedDate > std::chrono::hours(RdbRekeyTest::HOURS_EXPIRED)); + + RdbStoreConfig config = GetRdbConfig(RdbRekeyTest::encryptedDatabasePath); + RekeyTestOpenCallback helper; + int errCode; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + ASSERT_NE(store, nullptr); + + isFileExists = OHOS::FileExists(keyPath); + ASSERT_TRUE(isFileExists); + isFileExists = OHOS::FileExists(newKeyPath); + ASSERT_FALSE(isFileExists); + + auto newDate = GetKeyFileDate(encryptedDatabaseName); + ASSERT_TRUE(std::chrono::system_clock::now() - newDate < std::chrono::seconds(2)); + CheckQueryData(store); +} + +/** +* @tc.name: Rdb_Rekey_Test_002 +* @tc.desc: test RdbStore with not outdated password +* @tc.type: FUNC +*/ +HWTEST_F(RdbRekeyTest, Rdb_Rekey_02, TestSize.Level1) +{ + std::string keyPath = encryptedDatabaseKeyDir + RemoveSuffix(encryptedDatabaseName) + ".pub_key"; + bool isFileExists = OHOS::FileExists(keyPath); + ASSERT_TRUE(isFileExists); + + bool isFileDateChanged = ChangeKeyFileDate(encryptedDatabaseName, RdbRekeyTest::HOURS_NOT_EXPIRED); + ASSERT_TRUE(isFileDateChanged); + + auto changedDate = GetKeyFileDate(encryptedDatabaseName); + ASSERT_TRUE(std::chrono::system_clock::now() - changedDate > std::chrono::hours(RdbRekeyTest::HOURS_NOT_EXPIRED)); + + RdbStoreConfig config = GetRdbConfig(RdbRekeyTest::encryptedDatabasePath); + RekeyTestOpenCallback helper; + int errCode; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + ASSERT_NE(store, nullptr); + CheckQueryData(store); +} + +/** +* @tc.name: Rdb_Rekey_Test_003 +* @tc.desc: try to open store and execute RekeyRecover() without key and new key files. +* @tc.type: FUNC +*/ +HWTEST_F(RdbRekeyTest, Rdb_Rekey_03, TestSize.Level1) +{ + std::string keyPath = encryptedDatabaseKeyDir + RemoveSuffix(encryptedDatabaseName) + ".pub_key"; + std::string newKeyPath = encryptedDatabaseKeyDir + RemoveSuffix(encryptedDatabaseName) + ".pub_key.new"; + + bool isFileExists = OHOS::FileExists(keyPath); + ASSERT_TRUE(isFileExists); + + SqliteDatabaseUtils::DeleteFile(keyPath); + isFileExists = OHOS::FileExists(keyPath); + ASSERT_FALSE(isFileExists); + isFileExists = OHOS::FileExists(newKeyPath); + ASSERT_FALSE(isFileExists); + + RekeyTestOpenCallback helper; + int errCode; + RdbStoreConfig config = GetRdbConfig(encryptedDatabasePath); + std::shared_ptr store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + ASSERT_EQ(store, nullptr); +} \ No newline at end of file diff --git a/relational_store/test/native/rdb/unittest/rdb_value_bucket_test.cpp b/relational_store/test/native/rdb/unittest/rdb_value_bucket_test.cpp index 361653cd..b7b5ff48 100644 --- a/relational_store/test/native/rdb/unittest/rdb_value_bucket_test.cpp +++ b/relational_store/test/native/rdb/unittest/rdb_value_bucket_test.cpp @@ -166,7 +166,6 @@ HWTEST_F(ValuesBucketTest, Values_Bucket_002, TestSize.Level1) HWTEST_F(ValuesBucketTest, Values_Bucket_003, TestSize.Level1) { ValuesBucket values; - std::map getAllValuesMap; values.PutInt("id", 1); values.PutString("name", std::string("zhangsan")); values.PutLong("No.", 9223372036854775807L); @@ -175,11 +174,6 @@ HWTEST_F(ValuesBucketTest, Values_Bucket_003, TestSize.Level1) values.PutBlob("codes", std::vector{ 1, 2, 3 }); values.PutNull("mark"); - values.GetAll(getAllValuesMap); - EXPECT_EQ(7, getAllValuesMap.size()); - getAllValuesMap.clear(); - EXPECT_EQ(true, getAllValuesMap.empty()); - EXPECT_EQ(7, values.Size()); values.Clear(); EXPECT_EQ(true, values.IsEmpty()); @@ -242,3 +236,82 @@ HWTEST_F(ValuesBucketTest, Values_Object_001, TestSize.Level1) std::vector retVectorUint8 = ValueObject(valueVectorUint8); EXPECT_EQ(valueVectorUint8, retVectorUint8); } + +/** + * @tc.name: Convert from subset + * @tc.desc: test ValuesObject operator + * @tc.type: FUNC + */ +HWTEST_F(ValuesBucketTest, Convert_From_Subset, TestSize.Level1) +{ + ValueObject::Type output = AssetValue(); + using Type = std::variant>; + Type input; + ValueObject::Convert(input, output); + auto *nil = std::get_if(&output); + EXPECT_TRUE(nil != nullptr); + input = int64_t(54); + ValueObject::Convert(input, output); + auto *number = std::get_if(&output); + EXPECT_TRUE(number != nullptr); + EXPECT_TRUE(*number == 54); + input = double(1.1); + ValueObject::Convert(input, output); + auto *real = std::get_if(&output); + EXPECT_TRUE(real != nullptr); + input = std::string("my test"); + ValueObject::Convert(input, output); + auto *text = std::get_if(&output); + EXPECT_TRUE(text != nullptr); + EXPECT_TRUE(*text == "my test"); + input = std::vector(10, 'm'); + ValueObject::Convert(input, output); + auto *blob = std::get_if>(&output); + EXPECT_TRUE(blob != nullptr); + EXPECT_TRUE(*blob == std::vector(10, 'm')); +} + +/** + * @tc.name: Convert to subset + * @tc.desc: test ValuesObject operator + * @tc.type: FUNC + */ +HWTEST_F(ValuesBucketTest, Convert_To_Subset, TestSize.Level1) +{ + using Type = std::variant>; + Type output; + ValueObject::Type input; + ValueObject::Convert(input, output); + auto *nil = std::get_if(&output); + EXPECT_TRUE(nil != nullptr); + input = int64_t(54); + ValueObject::Convert(input, output); + auto *number = std::get_if(&output); + EXPECT_TRUE(number != nullptr); + EXPECT_TRUE(*number == 54); + input = double(1.1); + ValueObject::Convert(input, output); + auto *real = std::get_if(&output); + EXPECT_TRUE(real != nullptr); + input = std::string("my test"); + ValueObject::Convert(input, output); + auto *text = std::get_if(&output); + EXPECT_TRUE(text != nullptr); + EXPECT_TRUE(*text == "my test"); + input = std::vector(10, 'm'); + ValueObject::Convert(input, output); + auto *blob = std::get_if>(&output); + EXPECT_TRUE(blob != nullptr); + EXPECT_TRUE(*blob == std::vector(10, 'm')); + AssetValue value{.version = 0, .name = "123", .modifyTime = "12", .uri = "my test path" }; + input = value ; + output = {}; + ValueObject::Convert(input, output); + nil = std::get_if(&output); + EXPECT_TRUE(nil != nullptr); + input = std::vector(10, value); + output = {}; + ValueObject::Convert(input, output); + nil = std::get_if(&output); + EXPECT_TRUE(nil != nullptr); +} \ No newline at end of file -- Gitee From d192b614b916f5d86d7924efdad4296c1ad8e231 Mon Sep 17 00:00:00 2001 From: Sven Wang Date: Tue, 4 Apr 2023 16:02:47 +0800 Subject: [PATCH 07/44] update Signed-off-by: Sven Wang --- relational_store/frameworks/native/rdb/src/rdb_types_util.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/relational_store/frameworks/native/rdb/src/rdb_types_util.cpp b/relational_store/frameworks/native/rdb/src/rdb_types_util.cpp index f24c57d6..7a2fde1c 100644 --- a/relational_store/frameworks/native/rdb/src/rdb_types_util.cpp +++ b/relational_store/frameworks/native/rdb/src/rdb_types_util.cpp @@ -86,7 +86,7 @@ template<> bool ITypesUtil::Marshalling(const ValuesBucket &input, MessageParcel template<> bool ITypesUtil::Unmarshalling(ValuesBucket &output, MessageParcel &data) { - return ITypesUtil::Marshal(data, output.values_); + return ITypesUtil::Unmarshal(data, output.values_); } template<> bool ITypesUtil::Marshalling(const Asset &input, MessageParcel &data) -- Gitee From b9d027a1ef3c766f9c421ff2ec7959245d527b5c Mon Sep 17 00:00:00 2001 From: Sven Wang Date: Tue, 4 Apr 2023 18:01:29 +0800 Subject: [PATCH 08/44] update Signed-off-by: Sven Wang --- .../js/napi/common/include/js_utils.h | 173 ++++++++++++++---- .../js/napi/common/src/js_utils.cpp | 166 +---------------- .../frameworks/js/napi/rdb/BUILD.gn | 1 + .../js/napi/rdb/include/napi_rdb_js_utils.h | 28 +++ .../js/napi/rdb/src/napi_rdb_js_utils.cpp | 25 +++ .../js/napi/rdb/src/napi_rdb_store_helper.cpp | 2 +- .../napi/rdb/src/napi_rdb_store_observer.cpp | 2 +- .../js/napi/rdb/src/napi_values_bucket.cpp | 40 +--- 8 files changed, 202 insertions(+), 235 deletions(-) create mode 100644 relational_store/frameworks/js/napi/rdb/include/napi_rdb_js_utils.h create mode 100644 relational_store/frameworks/js/napi/rdb/src/napi_rdb_js_utils.cpp diff --git a/relational_store/frameworks/js/napi/common/include/js_utils.h b/relational_store/frameworks/js/napi/common/include/js_utils.h index 67aef256..3b04d6ab 100644 --- a/relational_store/frameworks/js/napi/common/include/js_utils.h +++ b/relational_store/frameworks/js/napi/common/include/js_utils.h @@ -19,6 +19,7 @@ #include #include #include +#include #include #include "napi/native_api.h" @@ -27,46 +28,138 @@ namespace OHOS { namespace AppDataMgrJsKit { -class JSUtils final { -public: - static constexpr int OK = 0; - static constexpr int ERR = -1; - static constexpr int32_t DEFAULT_BUF_SIZE = 1024; - // 1 is the margin - static constexpr int32_t BUF_CACHE_MARGIN = 4 + 1; - static constexpr int32_t ASYNC_RST_SIZE = 2; - static constexpr int32_t MAX_VALUE_LENGTH = 8 * 1024; - static constexpr int32_t SYNC_RESULT_ELEMNT_NUM = 2; - - static std::string Convert2String(napi_env env, napi_value jsStr, bool useDefaultBufSize = true); - static int32_t Convert2Bool(napi_env env, napi_value jsBool, bool &output); - static int32_t Convert2Double(napi_env env, napi_value jsNum, double &output); - static int32_t Convert2String(napi_env env, napi_value jsStr, std::string &output); - static int32_t Convert2U8Vector(napi_env env, napi_value jsValue, std::vector &output); - static std::vector Convert2StrVector(napi_env env, napi_value value); - static std::vector Convert2U8Vector(napi_env env, napi_value jsValue); - static std::string ConvertAny2String(napi_env env, const napi_value jsValue); - - static int32_t Convert2StrVector(napi_env env, napi_value value, std::vector &output); - static int32_t Convert2BoolVector(napi_env env, napi_value value, std::vector &output); - static int32_t Convert2DoubleVector(napi_env env, napi_value value, std::vector &output); - - static napi_value Convert2JSValue(napi_env env, const std::vector &value); - static napi_value Convert2JSValue(napi_env env, const std::string &value); - static napi_value Convert2JSValue(napi_env env, const std::vector &value); - static napi_value Convert2JSValue(napi_env env, int32_t value); - static napi_value Convert2JSValue(napi_env env, int64_t value); - static napi_value Convert2JSValue(napi_env env, double value); - static napi_value Convert2JSValue(napi_env env, bool value); - static napi_value Convert2JSValue(napi_env env, const std::map &value); - - static int32_t Convert2JSValue(napi_env env, std::string value, napi_value &output); - static int32_t Convert2JSValue(napi_env env, bool value, napi_value &output); - static int32_t Convert2JSValue(napi_env env, double value, napi_value &output); - static int32_t Convert2JSStringArr(napi_env env, std::vector value, napi_value &output); - static int32_t Convert2JSBoolArr(napi_env env, std::vector value, napi_value &output); - static int32_t Convert2JSDoubleArr(napi_env env, std::vector value, napi_value &output); -}; +namespace JSUtils { +constexpr int OK = 0; +constexpr int ERR = -1; +constexpr int32_t DEFAULT_BUF_SIZE = 1024; +// 1 is the margin +constexpr int32_t BUF_CACHE_MARGIN = 4 + 1; +constexpr int32_t ASYNC_RST_SIZE = 2; +constexpr int32_t MAX_VALUE_LENGTH = 8 * 1024; +constexpr int32_t SYNC_RESULT_ELEMNT_NUM = 2; + +std::string Convert2String(napi_env env, napi_value jsStr, bool useDefaultBufSize = true); +int32_t Convert2Value(napi_env env, napi_value jsBool, bool &output); +int32_t Convert2Value(napi_env env, napi_value jsNum, double &output); +int32_t Convert2Value(napi_env env, napi_value jsStr, std::string &output); +int32_t Convert2Value(napi_env env, napi_value jsValue, std::vector &output); +std::vector Convert2StrVector(napi_env env, napi_value value); +std::vector Convert2U8Vector(napi_env env, napi_value jsValue); +std::string ConvertAny2String(napi_env env, napi_value jsValue); + +template +int32_t Convert2Value(napi_env env, napi_value jsValue, T &output); +template +int32_t Convert2Value(napi_env env, napi_value jsValue, std::vector &value); +template +int32_t Convert2Value(napi_env env, napi_value jsValue, const std::variant<_Types...> &value); + +template +napi_value Convert2JSValue(napi_env env, const std::variant<_Types...> &value); + +int32_t Convert2JSValue(napi_env env, std::string value, napi_value &output); +int32_t Convert2JSValue(napi_env env, bool value, napi_value &output); +int32_t Convert2JSValue(napi_env env, double value, napi_value &output); + +napi_value Convert2JSValue(napi_env env, const std::vector &value); +napi_value Convert2JSValue(napi_env env, const std::string &value); +napi_value Convert2JSValue(napi_env env, const std::vector &value); +napi_value Convert2JSValue(napi_env env, int32_t value); +napi_value Convert2JSValue(napi_env env, int64_t value); +napi_value Convert2JSValue(napi_env env, double value); +napi_value Convert2JSValue(napi_env env, bool value); +napi_value Convert2JSValue(napi_env env, const std::map &value); +napi_value Convert2JSValue(napi_env env, const std::monostate &value); +template +napi_value Convert2JSValue(napi_env env, const T &value); +template +napi_value Convert2JSValue(napi_env env, const std::vector &value); + +template +napi_value Convert2JSValue(napi_env env, const std::variant<_Types...> &value); + +template +int32_t GetCPPValue(napi_env env, napi_value jsValue, _T &value) +{ + return napi_invalid_arg; +} + +template +int32_t GetCPPValue(napi_env env, napi_value jsValue, _T &value) +{ + _First cValue; + auto ret = Convert2Value(env, jsValue, cValue); + if (ret != napi_invalid_arg) { + if (ret == napi_ok) { + value = cValue; + } + return ret; + } + return GetCPPValue<_T, _Types...>(env, jsValue, value); +} + +template +napi_value GetJSValue(napi_env env, const _T &value) +{ + return nullptr; +} + +template +napi_value GetJSValue(napi_env env, const _T &value) +{ + auto *val = std::get_if<_First>(&value); + if (val == nullptr) { + return Convert2JSValue(env, *val); + } + return GetJSValue<_T, _Types...>(env, value); +} +} // namespace JSUtils + +template +int32_t JSUtils::Convert2Value(napi_env env, napi_value jsValue, std::vector &value) +{ + uint32_t arrLen = 0; + napi_get_array_length(env, value, &arrLen); + if (arrLen == 0) { + return napi_ok; + } + std::vector result; + for (size_t i = 0; i < arrLen; ++i) { + napi_value element; + napi_get_element(env, value, i, &element); + T value; + Convert2Value(env, element, value); + result.push_back(std::move(value)); + } + return napi_ok; +} + +template +int32_t JSUtils::Convert2Value(napi_env env, napi_value jsValue, const std::variant<_Types...> &value) +{ + return GetCPPValue(env, jsValue, value); +} + +template +napi_value JSUtils::Convert2JSValue(napi_env env, const std::vector &value) +{ + napi_value jsValue; + napi_status status = napi_create_array_with_length(env, value.size(), &jsValue); + if (status != napi_ok) { + return nullptr; + } + + for (size_t i = 0; i < value.size(); ++i) { + napi_set_element(env, jsValue, i, Convert2JSValue(env, value[i])); + } + return jsValue; +} + +template +napi_value JSUtils::Convert2JSValue(napi_env env, const std::variant<_Types...> &value) +{ + return GetJSValue(env, value); +} } // namespace AppDataMgrJsKit } // namespace OHOS diff --git a/relational_store/frameworks/js/napi/common/src/js_utils.cpp b/relational_store/frameworks/js/napi/common/src/js_utils.cpp index b87b3dee..a86b3838 100644 --- a/relational_store/frameworks/js/napi/common/src/js_utils.cpp +++ b/relational_store/frameworks/js/napi/common/src/js_utils.cpp @@ -39,17 +39,17 @@ std::string JSUtils::Convert2String(napi_env env, napi_value jsStr, bool useDefa return value; } -int32_t JSUtils::Convert2String(napi_env env, napi_value jsStr, std::string &output) +int32_t JSUtils::Convert2Value(napi_env env, napi_value jsStr, std::string &output) { char *str = new (std::nothrow) char[MAX_VALUE_LENGTH + 1]; if (str == nullptr) { - LOG_ERROR("JSUtils::Convert2String new failed, str is nullptr"); + LOG_ERROR("JSUtils::Convert2Value new failed, str is nullptr"); return ERR; } size_t valueSize = 0; napi_status status = napi_get_value_string_utf8(env, jsStr, str, MAX_VALUE_LENGTH, &valueSize); if (status != napi_ok) { - LOG_ERROR("JSUtils::Convert2String get jsVal failed, status = %{public}d", status); + LOG_ERROR("JSUtils::Convert2Value get jsVal failed, status = %{public}d", status); delete[] str; return ERR; } @@ -58,7 +58,7 @@ int32_t JSUtils::Convert2String(napi_env env, napi_value jsStr, std::string &out return OK; } -int32_t JSUtils::Convert2U8Vector(napi_env env, napi_value jsValue, std::vector &output) +int32_t JSUtils::Convert2Value(napi_env env, napi_value jsValue, std::vector &output) { bool isTypedArray = false; napi_is_typedarray(env, jsValue, &isTypedArray); @@ -79,24 +79,24 @@ int32_t JSUtils::Convert2U8Vector(napi_env env, napi_value jsValue, std::vector< return OK; } -int32_t JSUtils::Convert2Bool(napi_env env, napi_value jsBool, bool &output) +int32_t JSUtils::Convert2Value(napi_env env, napi_value jsBool, bool &output) { bool bValue = false; napi_status status = napi_get_value_bool(env, jsBool, &bValue); if (status != napi_ok) { - LOG_ERROR("JSUtils::Convert2Bool get jsVal failed, status = %{public}d", status); + LOG_ERROR("JSUtils::Convert2Value get jsVal failed, status = %{public}d", status); return ERR; } output = bValue; return OK; } -int32_t JSUtils::Convert2Double(napi_env env, napi_value jsNum, double &output) +int32_t JSUtils::Convert2Value(napi_env env, napi_value jsNum, double &output) { double number = 0.0; napi_status status = napi_get_value_double(env, jsNum, &number); if (status != napi_ok) { - LOG_ERROR("JSUtils::Convert2Double get jsVal failed, status = %{public}d", status); + LOG_ERROR("JSUtils::Convert2Value get jsVal failed, status = %{public}d", status); return ERR; } output = number; @@ -119,88 +119,6 @@ std::vector JSUtils::Convert2StrVector(napi_env env, napi_value val return result; } -int32_t JSUtils::Convert2StrVector(napi_env env, napi_value value, std::vector &output) -{ - uint32_t arrLen = 0; - napi_status status = napi_get_array_length(env, value, &arrLen); - if (status != napi_ok) { - LOG_ERROR("JSUtils::Convert2StrVector get arrLength failed, status = %{public}d", status); - output = {}; - return ERR; - } - if (arrLen == 0) { - output = {}; - return OK; - } - napi_value element = nullptr; - for (size_t i = 0; i < arrLen; ++i) { - status = napi_get_element(env, value, i, &element); - if (status != napi_ok) { - LOG_ERROR("JSUtils::Convert2StrVector get element failed, status = %{public}d", status); - return ERR; - } - std::string str; - if (Convert2String(env, element, str) != OK) { - LOG_ERROR("JSUtils::Convert2StrVector convert element failed"); - return ERR; - } - output.push_back(str); - } - return OK; -} - -int32_t JSUtils::Convert2BoolVector(napi_env env, napi_value value, std::vector &output) -{ - uint32_t arrLen = 0; - napi_status status = napi_get_array_length(env, value, &arrLen); - if (status != napi_ok) { - LOG_ERROR("JSUtils::Convert2BoolVector get arrLength failed, status = %{public}d", status); - output = {}; - return ERR; - } - napi_value element = nullptr; - for (size_t i = 0; i < arrLen; ++i) { - status = napi_get_element(env, value, i, &element); - if (status != napi_ok) { - LOG_ERROR("JSUtils::Convert2BoolVector get element failed, status = %{public}d", status); - return ERR; - } - bool bVal = false; - if (Convert2Bool(env, element, bVal) != OK) { - LOG_ERROR("JSUtils::Convert2BoolVector convert element failed"); - return ERR; - } - output.push_back(bVal); - } - return OK; -} - -int32_t JSUtils::Convert2DoubleVector(napi_env env, napi_value value, std::vector &output) -{ - uint32_t arrLen = 0; - napi_status status = napi_get_array_length(env, value, &arrLen); - if (status != napi_ok) { - LOG_ERROR("JSUtils::Convert2DoubleVector get arrLength failed, status = %{public}d", status); - output = {}; - return ERR; - } - napi_value element = nullptr; - for (size_t i = 0; i < arrLen; ++i) { - status = napi_get_element(env, value, i, &element); - if (status != napi_ok) { - LOG_ERROR("JSUtils::Convert2DoubleVector get element failed, status = %{public}d", status); - return ERR; - } - double number = 0.0; - if (Convert2Double(env, element, number) != OK) { - LOG_ERROR("JSUtils::Convert2Double convert element failed"); - return ERR; - } - output.push_back(number); - } - return OK; -} - std::vector JSUtils::Convert2U8Vector(napi_env env, napi_value input_array) { bool isTypedArray = false; @@ -379,73 +297,9 @@ int32_t JSUtils::Convert2JSValue(napi_env env, double value, napi_value &output) return OK; } -int32_t JSUtils::Convert2JSDoubleArr(napi_env env, std::vector value, napi_value &output) -{ - size_t arrLen = value.size(); - napi_status status = napi_create_array_with_length(env, arrLen, &output); - if (status != napi_ok) { - LOG_ERROR("JSUtils::Convert2JSValue get arrLength failed"); - return ERR; - } - for (size_t i = 0; i < arrLen; i++) { - napi_value val = nullptr; - if (Convert2JSValue(env, value[i], val) != OK) { - LOG_ERROR("JSUtils::Convert2JSValue creat double failed"); - return ERR; - } - status = napi_set_element(env, output, i, val); - if (status != napi_ok) { - LOG_ERROR("JSUtils::Convert2JSValue set element failed"); - return ERR; - } - } - return OK; -} - -int32_t JSUtils::Convert2JSBoolArr(napi_env env, std::vector value, napi_value &output) +napi_value JSUtils::Convert2JSValue(napi_env env, const std::monostate &value) { - size_t arrLen = value.size(); - napi_status status = napi_create_array_with_length(env, arrLen, &output); - if (status != napi_ok) { - LOG_ERROR("JSUtils::Convert2JSValue get arrLength failed"); - return ERR; - } - for (size_t i = 0; i < arrLen; i++) { - napi_value val = nullptr; - if (Convert2JSValue(env, value[i], val) != OK) { - LOG_ERROR("JSUtils::Convert2JSValue creat bool failed"); - return ERR; - } - status = napi_set_element(env, output, i, val); - if (status != napi_ok) { - LOG_ERROR("JSUtils::Convert2JSValue set element failed"); - return ERR; - } - } - return OK; -} - -int32_t JSUtils::Convert2JSStringArr(napi_env env, std::vector value, napi_value &output) -{ - size_t arrLen = value.size(); - napi_status status = napi_create_array_with_length(env, arrLen, &output); - if (status != napi_ok) { - LOG_ERROR("JSUtils::Convert2JSValue get arrLength failed"); - return ERR; - } - for (size_t i = 0; i < arrLen; i++) { - napi_value val = nullptr; - if (Convert2JSValue(env, value[i], val) != OK) { - LOG_ERROR("JSUtils::Convert2JSValue creat string failed"); - return ERR; - } - status = napi_set_element(env, output, i, val); - if (status != napi_ok) { - LOG_ERROR("JSUtils::Convert2JSValue set element failed"); - return ERR; - } - } - return OK; + return nullptr; } } // namespace AppDataMgrJsKit } // namespace OHOS diff --git a/relational_store/frameworks/js/napi/rdb/BUILD.gn b/relational_store/frameworks/js/napi/rdb/BUILD.gn index 26927461..01eb03de 100644 --- a/relational_store/frameworks/js/napi/rdb/BUILD.gn +++ b/relational_store/frameworks/js/napi/rdb/BUILD.gn @@ -27,6 +27,7 @@ ohos_shared_library("napi_rdb") { "../common/src/js_utils.cpp", "src/napi_async_call.cpp", "src/napi_rdb_const_properties.cpp", + "src/napi_rdb_js_utils.cpp", "src/napi_rdb_predicates.cpp", "src/napi_rdb_store.cpp", "src/napi_rdb_store_helper.cpp", diff --git a/relational_store/frameworks/js/napi/rdb/include/napi_rdb_js_utils.h b/relational_store/frameworks/js/napi/rdb/include/napi_rdb_js_utils.h new file mode 100644 index 00000000..def10f22 --- /dev/null +++ b/relational_store/frameworks/js/napi/rdb/include/napi_rdb_js_utils.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef RDB_JSKIT_NAPI_RDB_JS_UTILS_H +#define RDB_JSKIT_NAPI_RDB_JS_UTILS_H +#include "asset_value.h" +#include "value_object.h" +#include "js_utils.h" +namespace OHOS::AppDataMgrJsKit { +namespace JSUtils { +using Asset = OHOS::NativeRdb::AssetValue; +template<> +napi_value Convert2JSValue(napi_env env, const Asset &value); +}; // namespace JSUtils +} // namespace OHOS::AppDataMgrJsKit +#endif // RDB_JSKIT_NAPI_RDB_JS_UTILS_H diff --git a/relational_store/frameworks/js/napi/rdb/src/napi_rdb_js_utils.cpp b/relational_store/frameworks/js/napi/rdb/src/napi_rdb_js_utils.cpp new file mode 100644 index 00000000..90bde88d --- /dev/null +++ b/relational_store/frameworks/js/napi/rdb/src/napi_rdb_js_utils.cpp @@ -0,0 +1,25 @@ +/* + * 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. + */ + +#include "napi_rdb_js_utils.h" +namespace OHOS::AppDataMgrJsKit { +namespace JSUtils { +template<> +napi_value Convert2JSValue(napi_env env, const Asset &value) +{ + return nullptr; +} +}; // namespace JSUtils +} // namespace OHOS::AppDataMgrJsKit \ No newline at end of file diff --git a/relational_store/frameworks/js/napi/rdb/src/napi_rdb_store_helper.cpp b/relational_store/frameworks/js/napi/rdb/src/napi_rdb_store_helper.cpp index 64e2aa2e..7f1742ae 100644 --- a/relational_store/frameworks/js/napi/rdb/src/napi_rdb_store_helper.cpp +++ b/relational_store/frameworks/js/napi/rdb/src/napi_rdb_store_helper.cpp @@ -294,7 +294,7 @@ int ParseIsEncrypt(const napi_env &env, const napi_value &object, std::shared_pt napi_status status = napi_get_named_property(env, object, "encrypt", &value); if (status == napi_ok && value != nullptr) { bool isEncrypt = false; - JSUtils::Convert2Bool(env, value, isEncrypt); + JSUtils::Convert2Value(env, value, isEncrypt); context->config.SetEncryptStatus(isEncrypt); } return OK; diff --git a/relational_store/frameworks/js/napi/rdb/src/napi_rdb_store_observer.cpp b/relational_store/frameworks/js/napi/rdb/src/napi_rdb_store_observer.cpp index 8df0222e..8033cd54 100644 --- a/relational_store/frameworks/js/napi/rdb/src/napi_rdb_store_observer.cpp +++ b/relational_store/frameworks/js/napi/rdb/src/napi_rdb_store_observer.cpp @@ -18,7 +18,7 @@ #include "js_logger.h" #include "js_utils.h" -using OHOS::AppDataMgrJsKit::JSUtils; +using namespace OHOS::AppDataMgrJsKit; using OHOS::AppDataMgrJsKit::PREFIX_LABEL; namespace OHOS::RdbJsKit { diff --git a/relational_store/frameworks/js/napi/rdb/src/napi_values_bucket.cpp b/relational_store/frameworks/js/napi/rdb/src/napi_values_bucket.cpp index 1480ba52..d12e2b4c 100644 --- a/relational_store/frameworks/js/napi/rdb/src/napi_values_bucket.cpp +++ b/relational_store/frameworks/js/napi/rdb/src/napi_values_bucket.cpp @@ -27,43 +27,9 @@ __attribute__((visibility("default"))) napi_value NAPI_OHOS_Data_RdbJsKit_Values { napi_value ret; NAPI_CALL(env, napi_create_object(env, &ret)); - std::map valuesMap = valuesBucket.GetAll(); - std::map::iterator it; - for (it = valuesMap.begin(); it != valuesMap.end(); ++it) { - std::string key = it->first; - auto valueObject = it->second; - napi_value value = nullptr; - switch (valueObject.GetType()) { - case ValueObjectType::TYPE_NULL: { - value = nullptr; - } break; - case ValueObjectType::TYPE_INT: { - int64_t intVal = 0; - valueObject.GetLong(intVal); - value = JSUtils::Convert2JSValue(env, intVal); - } break; - case ValueObjectType::TYPE_DOUBLE: { - double doubleVal = 0L; - valueObject.GetDouble(doubleVal); - value = JSUtils::Convert2JSValue(env, doubleVal); - } break; - case ValueObjectType::TYPE_BLOB: { - std::vector blobVal; - valueObject.GetBlob(blobVal); - value = JSUtils::Convert2JSValue(env, blobVal); - } break; - case ValueObjectType::TYPE_BOOL: { - bool boolVal = false; - valueObject.GetBool(boolVal); - value = JSUtils::Convert2JSValue(env, boolVal); - } break; - default: { - std::string strVal = ""; - valueObject.GetString(strVal); - value = JSUtils::Convert2JSValue(env, strVal); - } break; - } - NAPI_CALL(env, napi_set_named_property(env, ret, key.c_str(), value)); + for (auto &[key, value]: valuesBucket.values_) { + napi_value jsValue = JSUtils::Convert2JSValue(env, value.value); + NAPI_CALL(env, napi_set_named_property(env, ret, key.c_str(), jsValue)); } return ret; -- Gitee From 780ef1e142c44568caaa313b769b21525ea3aa14 Mon Sep 17 00:00:00 2001 From: zuojiangjiang Date: Mon, 10 Apr 2023 12:54:52 +0000 Subject: [PATCH 09/44] !18 add proxy Merge pull request !18 from zuojiangjiang/cloud_dev --- .../framework/cloud/cloud_info.cpp | 22 ++- .../framework/include/cloud/cloud_info.h | 6 +- .../framework/include/eventcenter/event.h | 3 +- .../service/cloud/cloud_service_impl.cpp | 126 +++++++++++++++++- .../service/cloud/cloud_service_impl.h | 11 ++ .../service/cloud/cloud_syncer.cpp | 28 ++++ .../service/cloud/cloud_syncer.h | 30 +++++ .../service/rdb/rdb_event.cpp | 28 ++++ .../service/rdb/rdb_event.h | 38 ++++++ .../service/rdb/rdb_service_impl.cpp | 11 ++ .../service/rdb/rdb_service_impl.h | 2 + relational_store/CMakeLists.txt | 3 + .../cloud_data/include/cloud_manager_impl.h | 51 +++++++ .../cloud_data/include/cloud_service_proxy.h | 39 ++++++ .../cloud_data/include/icloud_service.h | 37 +++++ .../native/cloud_data/src/cloud_manager.cpp | 24 ++++ .../cloud_data/src/cloud_manager_impl.cpp | 122 +++++++++++++++++ .../cloud_data/src/cloud_service_proxy.cpp | 105 +++++++++++++++ .../frameworks/native/rdb/src/asset_value.cpp | 2 +- .../cloud_data/include/cloud_manager.h | 33 +++++ .../cloud_data/include/cloud_service.h | 9 ++ 21 files changed, 720 insertions(+), 10 deletions(-) create mode 100644 datamgr_service/services/distributeddataservice/service/cloud/cloud_syncer.cpp create mode 100644 datamgr_service/services/distributeddataservice/service/cloud/cloud_syncer.h create mode 100644 datamgr_service/services/distributeddataservice/service/rdb/rdb_event.cpp create mode 100644 datamgr_service/services/distributeddataservice/service/rdb/rdb_event.h create mode 100644 relational_store/frameworks/native/cloud_data/include/cloud_manager_impl.h create mode 100644 relational_store/frameworks/native/cloud_data/include/cloud_service_proxy.h create mode 100644 relational_store/frameworks/native/cloud_data/include/icloud_service.h create mode 100644 relational_store/frameworks/native/cloud_data/src/cloud_manager.cpp create mode 100644 relational_store/frameworks/native/cloud_data/src/cloud_manager_impl.cpp create mode 100644 relational_store/frameworks/native/cloud_data/src/cloud_service_proxy.cpp create mode 100644 relational_store/interfaces/inner_api/cloud_data/include/cloud_manager.h diff --git a/datamgr_service/services/distributeddataservice/framework/cloud/cloud_info.cpp b/datamgr_service/services/distributeddataservice/framework/cloud/cloud_info.cpp index 17d7b1f1..aff70ea7 100644 --- a/datamgr_service/services/distributeddataservice/framework/cloud/cloud_info.cpp +++ b/datamgr_service/services/distributeddataservice/framework/cloud/cloud_info.cpp @@ -14,6 +14,8 @@ */ #include "cloud/cloud_info.h" +#include "utils/constant.h" + namespace OHOS::DistributedData { bool CloudInfo::Marshal(Serializable::json &node) const { @@ -57,14 +59,26 @@ bool CloudInfo::AppInfo::Unmarshal(const Serializable::json &node) std::string CloudInfo::GetKey() const { - return std::string(); + return GetKey(INFO_PREFIX, { id, std::to_string(user), account }); } std::map CloudInfo::GetSchemaKey() const { - for (auto &app : apps) { - + std::map keys; + for (const auto &app : apps) { + const auto key = GetKey(SCHEMA_PREFIX, { id, std::to_string(user), account, app.bundleName }); + keys.insert_or_assign(app.bundleName, key); } - return std::map(); + return keys; +} + +std::string CloudInfo::GetPrefix(const std::initializer_list &fields) +{ + return GetKey(INFO_PREFIX, fields).append(Constant::KEY_SEPARATOR); +} + +std::string CloudInfo::GetKey(const std::string &prefix, const std::initializer_list &fields) +{ + return Constant::Join(prefix, Constant::KEY_SEPARATOR, fields); } } // namespace OHOS::DistributedData \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_info.h b/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_info.h index 22f37cbb..9148e8b2 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_info.h +++ b/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_info.h @@ -29,7 +29,8 @@ public: bool Unmarshal(const json &node) override; }; int32_t user = 0; - std::string id; + std::string id = ""; + std::string account = ""; uint64_t totalSpace = 0; uint64_t remainSpace = 0; bool enableCloud = false; @@ -37,6 +38,7 @@ public: std::string GetKey() const; std::map GetSchemaKey() const; + static std::string GetPrefix(const std::initializer_list &fields); bool Marshal(json &node) const override; bool Unmarshal(const json &node) override; @@ -44,6 +46,8 @@ public: private: static constexpr const char *INFO_PREFIX = "CLOUD_INFO"; static constexpr const char *SCHEMA_PREFIX = "CLOUD_SCHEMA"; + + static std::string GetKey(const std::string &prefix, const std::initializer_list &fields); }; } #endif // OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_CLOUD_CLOUD_INFO_H diff --git a/datamgr_service/services/distributeddataservice/framework/include/eventcenter/event.h b/datamgr_service/services/distributeddataservice/framework/include/eventcenter/event.h index d574e0f5..5ee3a433 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/eventcenter/event.h +++ b/datamgr_service/services/distributeddataservice/framework/include/eventcenter/event.h @@ -27,7 +27,8 @@ public: EVT_INVALID, EVT_INITED, EVT_UPDATE, - EVT_CUSTOM = 0x1000 + EVT_CUSTOM = 0x1000, + EVT_RDB = 0x2000 }; API_EXPORT Event(int32_t evtId); API_EXPORT Event(Event &&) noexcept = delete; diff --git a/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.cpp b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.cpp index b78e07b7..81b3ebde 100644 --- a/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.cpp +++ b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.cpp @@ -13,11 +13,26 @@ * limitations under the License. */ +#define LOG_TAG "CloudServiceImpl" + #include "cloud_service_impl.h" +#include "account/account_delegate.h" +#include "checker/checker_manager.h" +#include "cloud_syncer.h" +#include "cloud/cloud_server.h" +#include "eventcenter/event_center.h" #include "feature/feature_system.h" +#include "ipc_skeleton.h" +#include "kvstore_utils.h" +#include "log_print.h" +#include "metadata/meta_data_manager.h" +#include "rdb_event.h" + namespace OHOS::CloudData { using namespace DistributedData; +using namespace DistributedKv; +using namespace DistributedRdb; __attribute__((used)) CloudServiceImpl::Factory CloudServiceImpl::factory_; CloudServiceImpl::Factory::Factory() { FeatureSystem::GetInstance().RegisterCreator(CloudServiceImpl::SERVICE_NAME, [this]() { @@ -27,21 +42,85 @@ CloudServiceImpl::Factory::Factory() { return product_; }); } + CloudServiceImpl::Factory::~Factory() {} +CloudServiceImpl::CloudServiceImpl() +{ + EventCenter::GetInstance().Subscribe(RdbEvent::RDB_FEATURE_INIT, [this](const Event &event) { + auto &rdbEvent = static_cast(event); + auto user = AccountDelegate::GetInstance()->GetUserByToken(rdbEvent.GetTokenId()); + auto cloudInfo = CloudServer::GetInstance()->GetServerInfo(user); + if (cloudInfo.id.empty()) { + ZLOGI("no cloud server"); + return; + } + UpdateCloudInfo(cloudInfo); + UpdateSchema(cloudInfo); + }); +} + int32_t CloudServiceImpl::EnableCloud(const std::string &id, const std::map &switches) { - return 0; + std::lock_guard lg(mutex_); + CloudInfo cloudInfo; + if (GetCloudInfo(id, cloudInfo) != SUCCESS) { + return INVALID_ARGUMENT; + } + cloudInfo.enableCloud = true; + for (const auto &item : switches) { + std::string appId = GetAppId(item.first); + for (auto &app : cloudInfo.apps) { + if (app.appId == appId) { + app.cloudSwitch = item.second; + break; + } + } + } + if (!MetaDataManager::GetInstance().SaveMeta(cloudInfo.GetKey(), cloudInfo, true)) { + return ERROR; + } + return SUCCESS; } int32_t CloudServiceImpl::DisableCloud(const std::string &id) { - return 0; + std::lock_guard lg(mutex_); + CloudInfo cloudInfo; + if (GetCloudInfo(id, cloudInfo) != SUCCESS) { + return INVALID_ARGUMENT; + } + cloudInfo.enableCloud = false; + if (!MetaDataManager::GetInstance().SaveMeta(cloudInfo.GetKey(), cloudInfo, true)) { + return ERROR; + } + return SUCCESS; } int32_t CloudServiceImpl::ChangeAppSwitch(const std::string &id, const std::string &bundleName, int32_t appSwitch) { - return 0; + std::lock_guard lg(mutex_); + CloudInfo cloudInfo; + if (GetCloudInfo(id, cloudInfo) != SUCCESS) { + return INVALID_ARGUMENT; + } + bool exist = false; + std::string appId = GetAppId(bundleName); + for (auto &app : cloudInfo.apps) { + if (app.appId == appId) { + app.cloudSwitch = appSwitch; + exist = true; + break; + } + } + if (!exist) { + ZLOGE("bundleName:%{public}s", bundleName.c_str()); + return INVALID_ARGUMENT; + } + if (!MetaDataManager::GetInstance().SaveMeta(cloudInfo.GetKey(), cloudInfo, true)) { + return ERROR; + } + return SUCCESS; } int32_t CloudServiceImpl::Clean(const std::string &id, const std::map &actions) @@ -53,4 +132,45 @@ int32_t CloudServiceImpl::NotifyDataChange(const std::string &id, const std::str { return 0; } + +int32_t CloudServiceImpl::GetCloudInfo(const std::string &id, CloudInfo &cloudInfo) +{ + cloudInfo.id = id; + uint32_t tokenId = IPCSkeleton::GetCallingTokenID(); + cloudInfo.user = AccountDelegate::GetInstance()->GetUserByToken(tokenId); + cloudInfo.account = AccountDelegate::GetInstance()->GetCurrentAccountId(); + if (!MetaDataManager::GetInstance().LoadMeta(cloudInfo.GetKey(), cloudInfo, true)) { + ZLOGE("invalid argument id:%{public}s, user:%{public}d, account:%{public}s", + KvStoreUtils::ToBeAnonymous(cloudInfo.id).c_str(), cloudInfo.user, + KvStoreUtils::ToBeAnonymous(cloudInfo.account).c_str()); + return ERROR; + } + return SUCCESS; +} + +std::string CloudServiceImpl::GetAppId(const std::string &bundleName) +{ + CheckerManager::StoreInfo storeInfo; + storeInfo.uid = IPCSkeleton::GetCallingUid(); + storeInfo.tokenId = IPCSkeleton::GetCallingTokenID(); + storeInfo.bundleName = bundleName; + return CheckerManager::GetInstance().GetAppId(storeInfo); +} + +void CloudServiceImpl::UpdateCloudInfo(DistributedData::CloudInfo &cloudInfo) +{ + CloudInfo oldInfo; + if (!MetaDataManager::GetInstance().LoadMeta(cloudInfo.GetKey(), oldInfo, true)) { + MetaDataManager::GetInstance().SaveMeta(cloudInfo.GetKey(), cloudInfo, true); + return; + } + oldInfo.totalSpace = cloudInfo.totalSpace; + oldInfo.remainSpace = cloudInfo.remainSpace; + cloudInfo = oldInfo; + MetaDataManager::GetInstance().SaveMeta(oldInfo.GetKey(), oldInfo, true); +} + +void CloudServiceImpl::UpdateSchema(DistributedData::CloudInfo &cloudInfo) +{ +} } \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.h b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.h index 203bcc45..d2dec093 100644 --- a/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.h +++ b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.h @@ -15,10 +15,15 @@ #ifndef OHOS_DISTRIBUTED_DATA_SERVICES_CLOUD_CLOUD_SERVICE_IMPL_H #define OHOS_DISTRIBUTED_DATA_SERVICES_CLOUD_CLOUD_SERVICE_IMPL_H + +#include #include "cloud_service_stub.h" +#include "cloud/cloud_info.h" + namespace OHOS::CloudData { class CloudServiceImpl : public CloudServiceStub { public: + CloudServiceImpl(); ~CloudServiceImpl() = default; int32_t EnableCloud(const std::string &id, const std::map &switches) override; int32_t DisableCloud(const std::string &id) override; @@ -34,6 +39,12 @@ private: std::shared_ptr product_; }; static Factory factory_; + + void UpdateCloudInfo(DistributedData::CloudInfo &cloudInfo); + void UpdateSchema(DistributedData::CloudInfo &cloudInfo); + int32_t GetCloudInfo(const std::string &id, DistributedData::CloudInfo &cloudInfo); + std::string GetAppId(const std::string &bundleName); + std::mutex mutex_; }; } // namespace OHOS::DistributedData diff --git a/datamgr_service/services/distributeddataservice/service/cloud/cloud_syncer.cpp b/datamgr_service/services/distributeddataservice/service/cloud/cloud_syncer.cpp new file mode 100644 index 00000000..f920c5ec --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/cloud/cloud_syncer.cpp @@ -0,0 +1,28 @@ +/* + * 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. + */ + +#include "cloud_syncer.h" + +namespace OHOS::CloudData { +CloudSyncer &CloudSyncer::GetInstance() +{ + static CloudSyncer instance; + return instance; +} + +void CloudSyncer::Sync(const DistributedData::CloudInfo &cloudInfo) +{ +} +} // namespace OHOS::CloudData \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/cloud/cloud_syncer.h b/datamgr_service/services/distributeddataservice/service/cloud/cloud_syncer.h new file mode 100644 index 00000000..c9dd7971 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/cloud/cloud_syncer.h @@ -0,0 +1,30 @@ +/* + * 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_DISTRIBUTED_DATA_SERVICES_CLOUD_CLOUD_SYNCER_H +#define OHOS_DISTRIBUTED_DATA_SERVICES_CLOUD_CLOUD_SYNCER_H + +#include "cloud/cloud_info.h" + +namespace OHOS::CloudData { +class CloudSyncer { +public: + static CloudSyncer &GetInstance(); + void Sync(const DistributedData::CloudInfo &cloudInfo); + +private: +}; +} // namespace OHOS::CloudData +#endif // OHOS_DISTRIBUTED_DATA_SERVICES_CLOUD_CLOUD_SYNCER_H diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_event.cpp b/datamgr_service/services/distributeddataservice/service/rdb/rdb_event.cpp new file mode 100644 index 00000000..e968beb2 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_event.cpp @@ -0,0 +1,28 @@ +/* + * 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. + */ + +#include "rdb_event.h" + +namespace OHOS::DistributedRdb { +RdbEvent::RdbEvent(int32_t evtId, uint32_t tokenId) + : DistributedData::Event(evtId), tokenId_(tokenId) +{ +} + +uint32_t RdbEvent::GetTokenId() const +{ + return tokenId_; +} +} \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_event.h b/datamgr_service/services/distributeddataservice/service/rdb/rdb_event.h new file mode 100644 index 00000000..a70525a1 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_event.h @@ -0,0 +1,38 @@ +/* + * 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_DISTRIBUTED_DATA_SERVICES_RDB_RDB_EVENT_H +#define OHOS_DISTRIBUTED_DATA_SERVICES_RDB_RDB_EVENT_H + +#include "eventcenter/event.h" + +namespace OHOS::DistributedRdb { +class RdbEvent : public DistributedData::Event { +public: + enum : int32_t { + RDB_FEATURE_INIT = EVT_RDB, + RDB_CREATE, + RDB_BUTT + }; + + RdbEvent(int32_t evtId, uint32_t tokenId); + ~RdbEvent() = default; + uint32_t GetTokenId() const; + +private: + uint32_t tokenId_; +}; +} // namespace OHOS::DistributedRdb +#endif // OHOS_DISTRIBUTED_DATA_SERVICES_RDB_RDB_EVENT_H diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.cpp b/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.cpp index 6f7eb43c..a19ad18b 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.cpp +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.cpp @@ -19,11 +19,13 @@ #include "checker/checker_manager.h" #include "communicator/device_manager_adapter.h" #include "crypto_manager.h" +#include "eventcenter/event_center.h" #include "ipc_skeleton.h" #include "log_print.h" #include "metadata/meta_data_manager.h" #include "metadata/store_meta_data.h" #include "permission/permission_validator.h" +#include "rdb_event.h" #include "rdb_notifier_proxy.h" #include "types_export.h" #include "utils/anonymous.h" @@ -446,4 +448,13 @@ int32_t RdbServiceImpl::DestroyRDBTable(const RdbSyncerParam ¶m) delete syncer; return RDB_OK; } + +int32_t RdbServiceImpl::OnInitialize() +{ + EventCenter::Defer defer; + auto tokenId = IPCSkeleton::GetCallingTokenID(); + auto initEvt = std::make_unique(RdbEvent::RDB_FEATURE_INIT, tokenId); + EventCenter::GetInstance().PostEvent(std::move(initEvt)); + return RDB_OK; +} } // namespace OHOS::DistributedRdb diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.h b/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.h index 35f93b7c..3d2324bd 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.h +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.h @@ -56,6 +56,8 @@ public: int32_t ResolveAutoLaunch(const std::string &identifier, DistributedDB::AutoLaunchParam ¶m) override; + int32_t OnInitialize() override; + protected: int32_t DoSync(const RdbSyncerParam& param, const SyncOption& option, const RdbPredicates& predicates, SyncResult& result) override; diff --git a/relational_store/CMakeLists.txt b/relational_store/CMakeLists.txt index cbece15b..1fa45508 100644 --- a/relational_store/CMakeLists.txt +++ b/relational_store/CMakeLists.txt @@ -12,6 +12,7 @@ set(MOCK_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../mock) set(KV_STORE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../kv_store) add_definitions(-DNAPI_EXPERIMENTAL) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/frameworks/native/appdatafwk/src relational_store_src) +aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/frameworks/native/cloud_data/src relational_store_src) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/frameworks/native/dataability/src relational_store_src) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/frameworks/native/rdb/src relational_store_src) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/frameworks/native/rdb_data_ability_adapter/src relational_store_src) @@ -20,11 +21,13 @@ aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/frameworks/native/rdb_device_ma aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/frameworks/js/napi/common/src relational_store_src) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/frameworks/js/napi/dataability/src relational_store_src) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/frameworks/js/napi/rdb/src relational_store_src) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/frameworks/native/cloud_data/include) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/frameworks/native/rdb/include) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/frameworks/js/napi/common/include) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/frameworks/js/napi/dataability/include) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/frameworks/js/napi/rdb/include) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/interfaces/inner_api/appdatafwk/include) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/interfaces/inner_api/cloud_data/include) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/interfaces/inner_api/dataability/include) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/interfaces/inner_api/rdb/include) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/interfaces/inner_api/rdb_data_ability_adapter/include) diff --git a/relational_store/frameworks/native/cloud_data/include/cloud_manager_impl.h b/relational_store/frameworks/native/cloud_data/include/cloud_manager_impl.h new file mode 100644 index 00000000..2c8501ee --- /dev/null +++ b/relational_store/frameworks/native/cloud_data/include/cloud_manager_impl.h @@ -0,0 +1,51 @@ +/* + * 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_DISTRIBUTED_DATA_CLOUD_CLOUD_MANAGER_IMPL_H +#define OHOS_DISTRIBUTED_DATA_CLOUD_CLOUD_MANAGER_IMPL_H + +#include +#include "cloud_service.h" +#include "cloud_service_proxy.h" +#include "icloud_service.h" +#include "iremote_object.h" +#include "iremote_proxy.h" + +namespace OHOS::CloudData { +class CloudDataServiceProxy; +class CloudManagerImpl { +public: + static CloudManagerImpl &GetInstance(); + std::shared_ptr GetCloudService(); + +private: + CloudManagerImpl() = default; + ~CloudManagerImpl() = default; + static std::shared_ptr GetDistributedDataManager(); + sptr GetCloudServiceProxy(); + + std::shared_ptr distributedDataMgr_; + std::mutex mutex_; + std::shared_ptr cloudService_; +}; + +class CloudDataServiceProxy : public IRemoteProxy { +public: + explicit CloudDataServiceProxy(const sptr &impl); + ~CloudDataServiceProxy() = default; + sptr GetFeatureInterface(const std::string &name) override; +}; +} // namespace OHOS::CloudData +#endif // OHOS_DISTRIBUTED_DATA_CLOUD_CLOUD_MANAGER_IMPL_H diff --git a/relational_store/frameworks/native/cloud_data/include/cloud_service_proxy.h b/relational_store/frameworks/native/cloud_data/include/cloud_service_proxy.h new file mode 100644 index 00000000..8ece3de8 --- /dev/null +++ b/relational_store/frameworks/native/cloud_data/include/cloud_service_proxy.h @@ -0,0 +1,39 @@ +/* + * 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_DISTRIBUTED_DATA_CLOUD_CLOUD_SERVICE_PROXY_H +#define OHOS_DISTRIBUTED_DATA_CLOUD_CLOUD_SERVICE_PROXY_H + +#include "icloud_service.h" +#include "iremote_object.h"" +#include "iremote_proxy.h" + +namespace OHOS::CloudData { +class CloudServiceProxy: public IRemoteProxy { +public: + explicit CloudServiceProxy(const sptr& object); + virtual ~CloudServiceProxy() = default; + int32_t EnableCloud(const std::string &id, const std::map &switches) override; + int32_t DisableCloud(const std::string &id) override; + int32_t ChangeAppSwitch(const std::string &id, const std::string &bundleName, int32_t appSwitch) override; + int32_t Clean(const std::string &id, const std::map &actions) override; + int32_t NotifyDataChange(const std::string &id, const std::string &bundleName) override; + +private: + sptr remote_; + static inline BrokerDelegator delegator_; +}; +} // namespace OHOS::CloudData +#endif // OHOS_DISTRIBUTED_DATA_CLOUD_CLOUD_SERVICE_PROXY_H diff --git a/relational_store/frameworks/native/cloud_data/include/icloud_service.h b/relational_store/frameworks/native/cloud_data/include/icloud_service.h new file mode 100644 index 00000000..a21def4f --- /dev/null +++ b/relational_store/frameworks/native/cloud_data/include/icloud_service.h @@ -0,0 +1,37 @@ +/* + * 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_DISTRIBUTED_DATA_CLOUD_ICLOUD_SERVICE_H +#define OHOS_DISTRIBUTED_DATA_CLOUD_ICLOUD_SERVICE_H + +#include "cloud_service.h" +#include "iremote_broker.h" + +namespace OHOS::CloudData { +class ICloudService : public CloudService, public IRemoteBroker { +public: + DECLARE_INTERFACE_DESCRIPTOR(u"OHOS.CloudData.CloudServer"); +}; + +class IKvStoreDataService : public IRemoteBroker { +public: + enum { GET_FEATURE_INTERFACE = 0 }; + + virtual sptr GetFeatureInterface(const std::string &name) = 0; + + DECLARE_INTERFACE_DESCRIPTOR(u"OHOS.DistributedKv.IKvStoreDataService"); +}; +} // namespace OHOS::CloudData +#endif // OHOS_DISTRIBUTED_DATA_CLOUD_ICLOUD_SERVICE_H diff --git a/relational_store/frameworks/native/cloud_data/src/cloud_manager.cpp b/relational_store/frameworks/native/cloud_data/src/cloud_manager.cpp new file mode 100644 index 00000000..c9a921c9 --- /dev/null +++ b/relational_store/frameworks/native/cloud_data/src/cloud_manager.cpp @@ -0,0 +1,24 @@ +/* + * 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. + */ + +#include "cloud_manager.h" +#include "cloud_manager_impl.h" + +namespace OHOS::CloudData { +std::shared_ptr CloudManager::GetCloudService() +{ + return CloudManagerImpl::GetInstance().GetCloudService(); +} +} // namespace OHOS::CloudData \ No newline at end of file diff --git a/relational_store/frameworks/native/cloud_data/src/cloud_manager_impl.cpp b/relational_store/frameworks/native/cloud_data/src/cloud_manager_impl.cpp new file mode 100644 index 00000000..f74edb1d --- /dev/null +++ b/relational_store/frameworks/native/cloud_data/src/cloud_manager_impl.cpp @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "CloudManagerImpl" + +#include "cloud_manager_impl.h" +#include "itypes_util.h" +#include "iservice_registry.h" +#include "log_print.h" +#include "system_ability_definition.h" + +namespace OHOS::CloudData { +CloudManagerImpl &CloudManagerImpl::GetInstance() +{ + static CloudManagerImpl instance; + return instance; +} + +std::shared_ptr CloudManagerImpl::GetCloudService() +{ + std::lock_guard lg(mutex_); + if (cloudService_ != nullptr) { + return cloudService_; + } + auto proxy = GetCloudServiceProxy(); + if (proxy == nullptr) { + return nullptr; + } + cloudService_ = std::shared_ptr(proxy.GetRefPtr(), [holder = proxy] (const auto*) {}); + if (cloudService_ == nullptr) { + return nullptr; + } + return cloudService_; +} + +sptr CloudManagerImpl::GetCloudServiceProxy() +{ + if (distributedDataMgr_ == nullptr) { + distributedDataMgr_ = GetDistributedDataManager(); + } + if (distributedDataMgr_ == nullptr) { + ZLOGE("get distributed data manager failed"); + return nullptr; + } + + auto remote = distributedDataMgr_->GetFeatureInterface(CloudService::SERVICE_NAME); + if (remote == nullptr) { + ZLOGE("get cloud service failed"); + return nullptr; + } + return iface_cast(remote); +} + +CloudDataServiceProxy::CloudDataServiceProxy(const sptr &impl) + : IRemoteProxy(impl) +{ + ZLOGI("init proxy"); +} + +std::shared_ptr CloudManagerImpl::GetDistributedDataManager() +{ + auto abilityMgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + if (abilityMgr == nullptr) { + ZLOGE("get system ability manager failed"); + return nullptr; + } + auto remoteObject = abilityMgr->CheckSystemAbility(DISTRIBUTED_KV_DATA_SERVICE_ABILITY_ID); + if (remoteObject == nullptr) { + ZLOGE("get distributed data manager failed"); + return nullptr; + } + sptr proxy = new(std::nothrow) CloudDataServiceProxy(remoteObject); + if (proxy == nullptr) { + ZLOGE("new CloudDataServiceProxy failed"); + return nullptr; + } + return std::shared_ptr(proxy.GetRefPtr(), + [holder = proxy](const auto *) {}); +} + +sptr CloudDataServiceProxy::GetFeatureInterface(const std::string &name) +{ + ZLOGI("%s", name.c_str()); + MessageParcel data; + if (!data.WriteInterfaceToken(CloudDataServiceProxy::GetDescriptor())) { + ZLOGE("write descriptor failed"); + return nullptr; + } + + if (!ITypesUtil::Marshal(data, name)) { + ZLOGE("write descriptor failed"); + return nullptr; + } + + MessageParcel reply; + MessageOption mo { MessageOption::TF_SYNC }; + int32_t error = Remote()->SendRequest(GET_FEATURE_INTERFACE, data, reply, mo); + if (error != 0) { + ZLOGE("SendRequest returned %{public}d", error); + return nullptr; + } + + sptr remoteObject; + if (!ITypesUtil::Unmarshal(reply, remoteObject)) { + ZLOGE("remote object is nullptr"); + return nullptr; + } + return remoteObject; +} +} // namespace OHOS::CloudData \ No newline at end of file diff --git a/relational_store/frameworks/native/cloud_data/src/cloud_service_proxy.cpp b/relational_store/frameworks/native/cloud_data/src/cloud_service_proxy.cpp new file mode 100644 index 00000000..fd295595 --- /dev/null +++ b/relational_store/frameworks/native/cloud_data/src/cloud_service_proxy.cpp @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "CloudServiceProxy" + +#include "cloud_service_proxy.h" +#include "itypes_util.h" +#include "log_print.h" + +namespace OHOS::CloudData { +#define IPC_SEND(code, reply, ...) \ +({ \ + int32_t __status = SUCCESS; \ + do { \ + MessageParcel request; \ + if (!request.WriteInterfaceToken(GetDescriptor())) { \ + __status = IPC_PARCEL_ERROR; \ + break; \ + } \ + if (!ITypesUtil::Marshal(request, ##__VA_ARGS__)) { \ + __status = IPC_PARCEL_ERROR; \ + break; \ + } \ + MessageOption option; \ + auto result = remote_->SendRequest((code), request, reply, option); \ + if (result != 0) { \ + __status = IPC_ERROR; \ + break; \ + } \ + \ + ITypesUtil::Unmarshal(reply, __status); \ + } while (0); \ + __status; \ +}) + +CloudServiceProxy::CloudServiceProxy(const sptr &object) + : IRemoteProxy(object) +{ + remote_ = Remote(); +} + +int32_t CloudServiceProxy::EnableCloud(const std::string &id, const std::map &switches) +{ + MessageParcel reply; + int32_t status = IPC_SEND(TRANS_ENABLE_CLOUD, reply, id, switches); + if (status != SUCCESS) { + ZLOGE("status:0x%{public}x id:%{public}.6s size:%{public}zu", status, id.c_str(), switches.size()); + } + return static_cast(status); +} + +int32_t CloudServiceProxy::DisableCloud(const std::string &id) +{ + MessageParcel reply; + int32_t status = IPC_SEND(TRANS_DISABLE_CLOUD, reply, id); + if (status != SUCCESS) { + ZLOGE("status:0x%{public}x id:%{public}.6s", status, id.c_str()); + } + return static_cast(status); +} + +int32_t CloudServiceProxy::ChangeAppSwitch(const std::string &id, const std::string &bundleName, int32_t appSwitch) +{ + MessageParcel reply; + int32_t status = IPC_SEND(TRANS_CHANGE_APP_SWITCH, reply, id, bundleName, appSwitch); + if (status != SUCCESS) { + ZLOGE("status:0x%{public}x id:%{public}.6s bundleName:%{public}s switch:%{public}d", + status, id.c_str(), bundleName.c_str(), appSwitch); + } + return static_cast(status); +} + +int32_t CloudServiceProxy::Clean(const std::string &id, const std::map &actions) +{ + MessageParcel reply; + int32_t status = IPC_SEND(TRANS_CLEAN, reply, id, actions); + if (status != SUCCESS) { + ZLOGE("status:0x%{public}x id:%{public}.6s size:%{public}zu", status, id.c_str(), actions.size()); + } + return static_cast(status); + +} + +int32_t CloudServiceProxy::NotifyDataChange(const std::string &id, const std::string &bundleName) +{ + MessageParcel reply; + int32_t status = IPC_SEND(TRANS_NOTIFY_DATA_CHANGE, reply, id, bundleName); + if (status != SUCCESS) { + ZLOGE("status:0x%{public}x id:%{public}.6s bundleName:%{public}s", status, id.c_str(), bundleName.c_str()); + } + return static_cast(status); +} +} // namespace OHOS::CloudData \ No newline at end of file diff --git a/relational_store/frameworks/native/rdb/src/asset_value.cpp b/relational_store/frameworks/native/rdb/src/asset_value.cpp index 43ebaa05..6b8c7ae5 100644 --- a/relational_store/frameworks/native/rdb/src/asset_value.cpp +++ b/relational_store/frameworks/native/rdb/src/asset_value.cpp @@ -13,4 +13,4 @@ * limitations under the License. */ -#include "asset_value.h" +#include "asset_value.h" \ No newline at end of file diff --git a/relational_store/interfaces/inner_api/cloud_data/include/cloud_manager.h b/relational_store/interfaces/inner_api/cloud_data/include/cloud_manager.h new file mode 100644 index 00000000..b17c49de --- /dev/null +++ b/relational_store/interfaces/inner_api/cloud_data/include/cloud_manager.h @@ -0,0 +1,33 @@ +/* + * 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_DISTRIBUTED_DATA_CLOUD_CLOUD_MANAGER_H +#define OHOS_DISTRIBUTED_DATA_CLOUD_CLOUD_MANAGER_H + +#include +#include +#include "cloud_service.h" +#include "rdb_visibility.h" + +namespace OHOS::CloudData { +class RDB_API_EXPORT CloudManager final { +public: + /** + * @brief Obtain cloud service. + */ + static std::shared_ptr GetCloudService(); +}; +} // namespace OHOS::CloudData +#endif // OHOS_DISTRIBUTED_DATA_CLOUD_CLOUD_MANAGER_H diff --git a/relational_store/interfaces/inner_api/cloud_data/include/cloud_service.h b/relational_store/interfaces/inner_api/cloud_data/include/cloud_service.h index 260c1a06..c7016761 100644 --- a/relational_store/interfaces/inner_api/cloud_data/include/cloud_service.h +++ b/relational_store/interfaces/inner_api/cloud_data/include/cloud_service.h @@ -44,6 +44,15 @@ public: SWITCH_OFF }; + enum Status : int32_t + { + SUCCESS = 0, + ERROR, + INVALID_ARGUMENT, + IPC_ERROR, + IPC_PARCEL_ERROR + }; + static constexpr const char *SERVICE_NAME = "cloud"; virtual ~CloudService() = default; virtual int32_t EnableCloud(const std::string &id, const std::map &switches) = 0; -- Gitee From d94b974c693eb0070c58cd017c8a34b380ac4fda Mon Sep 17 00:00:00 2001 From: Sven Wang Date: Wed, 12 Apr 2023 20:36:32 +0800 Subject: [PATCH 10/44] update Signed-off-by: Sven Wang --- .../framework/include/store/auto_cache.h | 29 +++- .../framework/include/store/general_store.h | 12 +- .../framework/include/store/general_watcher.h | 3 +- .../framework/store/auto_cache.cpp | 147 ++++++++++++++++++ kv_store/frameworks/common/task_scheduler.h | 5 + 5 files changed, 190 insertions(+), 6 deletions(-) diff --git a/datamgr_service/services/distributeddataservice/framework/include/store/auto_cache.h b/datamgr_service/services/distributeddataservice/framework/include/store/auto_cache.h index e1d4ee55..d0c75b35 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/store/auto_cache.h +++ b/datamgr_service/services/distributeddataservice/framework/include/store/auto_cache.h @@ -16,6 +16,7 @@ #ifndef OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_STORE_STORE_AUTO_CACHE_H #define OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_STORE_STORE_AUTO_CACHE_H #include +#include #include "concurrent_map.h" #include "metadata/store_meta_data.h" @@ -25,19 +26,41 @@ namespace OHOS::DistributedData { class AutoCache { public: + using Error = GeneralStore::ErrorCode; using Store = std::shared_ptr; + using Watcher = GeneralWatcher; + using Watchers = std::set>; using Time = std::chrono::steady_clock::time_point; using Executor = TaskScheduler; + using Creator = std::function; + static AutoCache &Instance(); AutoCache(std::shared_ptr executor); - Store Get(const StoreMetaData &data, std::shared_ptr watchers, int32_t &status); - + ~AutoCache(); + Store GetStore(const StoreMetaData &meta, const Watchers &watchers); + int32_t RegCreator(int32_t type, Creator creator); private: void GarbageCollect(); + struct Delegate : public GeneralWatcher { + Delegate(GeneralStore *delegate, const Watchers &observers); + ~Delegate(); + operator Store (); + bool operator<(const Time &time) const; + bool Close(); + void SetObservers(const Watchers &watchers); + int32_t OnChange(Origin origin, const std::string &id) override; + int32_t OnChange(Origin origin, const std::string &id, const std::vector &values) override; + private: + mutable Time time_; + GeneralStore *store_ = nullptr; + Watchers watchers_; + std::shared_mutex mutex_; + }; static constexpr int64_t INTERVAL = 1; static constexpr size_t TIME_TASK_NUM = 1; - ConcurrentMap> stores_; std::shared_ptr executor_; + ConcurrentMap> stores_; + std::vector creators_; }; } // namespace OHOS::DistributedData diff --git a/datamgr_service/services/distributeddataservice/framework/include/store/general_store.h b/datamgr_service/services/distributeddataservice/framework/include/store/general_store.h index 86d84236..8f5c93f4 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/store/general_store.h +++ b/datamgr_service/services/distributeddataservice/framework/include/store/general_store.h @@ -23,6 +23,13 @@ namespace OHOS::DistributedData { class GeneralStore { public: + enum ErrorCode : int32_t { + E_OK = 0, + E_ERROR, + E_BUSY, + E_INVALID_ARGS, + E_BUTT, + }; using Assets = std::vector; using Bytes = std::vector; using Value = std::variant; @@ -30,12 +37,13 @@ public: using VBucket = std::map; virtual ~GeneralStore() = default; virtual int32_t Close() = 0; + virtual int32_t Execute(const std::string &table, const std::string &sql) = 0; virtual int32_t Insert(const std::string &table, VBucket &&values) = 0; virtual int32_t Update(const std::string &table, const std::string &sql, VBucket &&values) = 0; virtual int32_t Delete(const std::string &table, const std::string &sql, Values &&args) = 0; virtual std::shared_ptr Query(const std::string &table, const std::string &sql, Values &&args) = 0; - virtual int32_t Watch(int32_t origin, std::shared_ptr watcher) = 0; - virtual int32_t Unwatch(int32_t origin, std::shared_ptr watcher) = 0; + virtual int32_t Watch(int32_t origin, GeneralWatcher &watcher) = 0; + virtual int32_t Unwatch(int32_t origin, GeneralWatcher &watcher) = 0; }; } // namespace OHOS::DistributedData #endif // OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_STORE_GENERAL_STORE_H diff --git a/datamgr_service/services/distributeddataservice/framework/include/store/general_watcher.h b/datamgr_service/services/distributeddataservice/framework/include/store/general_watcher.h index cc67afe6..4b8078df 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/store/general_watcher.h +++ b/datamgr_service/services/distributeddataservice/framework/include/store/general_watcher.h @@ -30,6 +30,7 @@ public: ORIGIN_CLOUD, ORIGIN_LOCAL, ORIGIN_REMOTE, + ORIGIN_ALL, ORIGIN_BUTT, }; enum ChangeOp : int32_t { @@ -45,7 +46,7 @@ public: using VBucket = std::map; API_EXPORT virtual ~GeneralWatcher() = default; virtual int32_t OnChange(Origin origin, const std::string &id) = 0; - virtual int32_t OnChange(Origin origin, const std::string &id, std::vector &&values) = 0; + virtual int32_t OnChange(Origin origin, const std::string &id, const std::vector &values) = 0; }; } #endif // OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_STORE_GENERAL_WATCHER_H diff --git a/datamgr_service/services/distributeddataservice/framework/store/auto_cache.cpp b/datamgr_service/services/distributeddataservice/framework/store/auto_cache.cpp index c7ed4de0..c2bfdca5 100644 --- a/datamgr_service/services/distributeddataservice/framework/store/auto_cache.cpp +++ b/datamgr_service/services/distributeddataservice/framework/store/auto_cache.cpp @@ -14,3 +14,150 @@ */ #include "store/auto_cache.h" +namespace OHOS::DistributedData { +AutoCache::AutoCache(std::shared_ptr executor) : executor_(executor) {} +AutoCache::~AutoCache() +{ + stores_.EraseIf([](int32_t tokenId, std::map &stores) -> bool { + for (auto &[key, store] : stores) { + store.Close(); + } + return true; + }); +} + +AutoCache::Store AutoCache::GetStore(const StoreMetaData &meta, const Watchers &watchers) +{ + Store store; + stores_.Compute(meta.tokenId, + [this, &meta, &watchers, &store](auto &, std::map &stores) -> bool { + auto it = stores.find(meta.storeId); + if (it != stores.end()) { + it->second.SetObservers(watchers); + store = it->second; + return !stores.empty(); + } + auto *dbStore = creators_[meta.storeType](meta); + if (dbStore == nullptr) { + return !stores.empty(); + } + auto result = stores.emplace(std::piecewise_construct, std::forward_as_tuple(meta.storeId), + std::forward_as_tuple(dbStore, watchers)); + store = result.first->second; + return !stores.empty(); + }); + executor_->Scheduler(std::chrono::steady_clock::now() + std::chrono::minutes(INTERVAL), + std::bind(&AutoCache::GarbageCollect, this)); + return store; +} + +int32_t AutoCache::RegCreator(int32_t type, Creator creator) +{ + if (type >= creators_.size()) { + creators_.resize(type + 1); + } + creators_[type] = creator; + return 0; +} + +void AutoCache::GarbageCollect() +{ + auto current = std::chrono::steady_clock::now(); + stores_.EraseIf([¤t](auto &key, std::map &delegates) { + for (auto it = delegates.begin(); it != delegates.end();) { + // if the kv store is BUSY we wait more INTERVAL minutes again + if ((it->second < current) && it->second.Close()) { + it = delegates.erase(it); + } else { + ++it; + } + } + return delegates.empty(); + }); + if (!stores_.Empty()) { + executor_->Scheduler(current + std::chrono::minutes(INTERVAL), std::bind(&AutoCache::GarbageCollect, this)); + } +} + +AutoCache::Delegate::Delegate(GeneralStore *delegate, const Watchers &watchers) + : store_(delegate), watchers_(watchers) +{ + time_ = std::chrono::steady_clock::now() + std::chrono::minutes(INTERVAL); + if (store_ != nullptr) { + store_->Watch(ORIGIN_ALL, *this); + } +} + +AutoCache::Delegate::~Delegate() +{ + if (store_ != nullptr) { + store_->Unwatch(ORIGIN_ALL, *this); + store_->Close(); + store_ = nullptr; + } +} + +AutoCache::Delegate::operator Store() +{ + time_ = std::chrono::steady_clock::now() + std::chrono::minutes(INTERVAL); + return Store(store_, [](GeneralStore *) {}); +} + +bool AutoCache::Delegate::operator<(const AutoCache::Time &time) const +{ + return time_ < time; +} + +bool AutoCache::Delegate::Close() +{ + std::unique_lock lock(mutex_); + if (store_ != nullptr) { + store_->Unwatch(ORIGIN_ALL, *this); + } + + auto status = store_->Close(); + if (status == Error::E_BUSY) { + return false; + } + store_ = nullptr; + return true; +} + +void AutoCache::Delegate::SetObservers(const AutoCache::Watchers &watchers) +{ + std::unique_lock lock(mutex_); + watchers_ = watchers; +} + +int32_t AutoCache::Delegate::OnChange(Origin origin, const std::string &id) +{ + Watchers watchers; + { + std::unique_lock lock(mutex_); + watchers = watchers_; + } + for (auto watcher : watchers) { + if (watcher == nullptr) { + continue; + } + watcher->OnChange(origin, id); + } + return Error::E_OK; +} + +int32_t AutoCache::Delegate::OnChange(Origin origin, const std::string &id, const std::vector &values) +{ + Watchers watchers; + { + std::unique_lock lock(mutex_); + watchers = watchers_; + } + for (auto watcher : watchers) { + if (watcher == nullptr) { + continue; + } + watcher->OnChange(origin, id, values); + } + return Error::E_OK; +} +} // namespace OHOS::DistributedData diff --git a/kv_store/frameworks/common/task_scheduler.h b/kv_store/frameworks/common/task_scheduler.h index 478fff8e..a8144e92 100644 --- a/kv_store/frameworks/common/task_scheduler.h +++ b/kv_store/frameworks/common/task_scheduler.h @@ -61,6 +61,11 @@ public: thread_->join(); } + TaskId Scheduler(const Time &begin, Task task, Duration interval = INVALID_INTERVAL, + uint64_t times = UNLIMITED_TIMES) + { + return At(begin, task, interval, times); + } // execute task at specific time TaskId At(const Time &begin, Task task, Duration interval = INVALID_INTERVAL, uint64_t times = UNLIMITED_TIMES) { -- Gitee From b6428585f92d1c69a82bcab557c70d9f1e69ec9b Mon Sep 17 00:00:00 2001 From: Sven Wang Date: Thu, 13 Apr 2023 10:14:48 +0800 Subject: [PATCH 11/44] update Signed-off-by: Sven Wang --- .../framework/include/store/auto_cache.h | 19 ++- .../framework/store/auto_cache.cpp | 109 ++++++++++++++---- 2 files changed, 98 insertions(+), 30 deletions(-) diff --git a/datamgr_service/services/distributeddataservice/framework/include/store/auto_cache.h b/datamgr_service/services/distributeddataservice/framework/include/store/auto_cache.h index d0c75b35..58255f0f 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/store/auto_cache.h +++ b/datamgr_service/services/distributeddataservice/framework/include/store/auto_cache.h @@ -32,20 +32,27 @@ public: using Watchers = std::set>; using Time = std::chrono::steady_clock::time_point; using Executor = TaskScheduler; + using TaskId = TaskScheduler::TaskId; using Creator = std::function; static AutoCache &Instance(); - AutoCache(std::shared_ptr executor); - ~AutoCache(); - Store GetStore(const StoreMetaData &meta, const Watchers &watchers); int32_t RegCreator(int32_t type, Creator creator); + void Bind(std::shared_ptr executor); + Store GetStore(const StoreMetaData &meta, const Watchers &watchers); + void CloseStore(uint32_t tokenId, const std::string &storeId); + void CloseExcept(const std::set &users); + void SetObserver(uint32_t tokenId, const std::string &storeId, const Watchers &watchers); + private: - void GarbageCollect(); + AutoCache(); + ~AutoCache(); + void GarbageCollect(bool isForce); struct Delegate : public GeneralWatcher { - Delegate(GeneralStore *delegate, const Watchers &observers); + Delegate(GeneralStore *delegate, const Watchers &watchers, int32_t user); ~Delegate(); operator Store (); bool operator<(const Time &time) const; bool Close(); + int32_t GetUser() const; void SetObservers(const Watchers &watchers); int32_t OnChange(Origin origin, const std::string &id) override; int32_t OnChange(Origin origin, const std::string &id, const std::vector &values) override; @@ -54,11 +61,13 @@ private: mutable Time time_; GeneralStore *store_ = nullptr; Watchers watchers_; + int32_t user_; std::shared_mutex mutex_; }; static constexpr int64_t INTERVAL = 1; static constexpr size_t TIME_TASK_NUM = 1; std::shared_ptr executor_; + TaskId taskId_ = Executor::INVALID_TASK_ID; ConcurrentMap> stores_; std::vector creators_; }; diff --git a/datamgr_service/services/distributeddataservice/framework/store/auto_cache.cpp b/datamgr_service/services/distributeddataservice/framework/store/auto_cache.cpp index c2bfdca5..990f1b90 100644 --- a/datamgr_service/services/distributeddataservice/framework/store/auto_cache.cpp +++ b/datamgr_service/services/distributeddataservice/framework/store/auto_cache.cpp @@ -12,18 +12,43 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - +#define LOG_TAG "AutoCache" #include "store/auto_cache.h" + +#include namespace OHOS::DistributedData { -AutoCache::AutoCache(std::shared_ptr executor) : executor_(executor) {} +AutoCache &AutoCache::Instance() +{ + static AutoCache cache; + return cache; +} + +int32_t AutoCache::RegCreator(int32_t type, Creator creator) +{ + if (type >= creators_.size()) { + creators_.resize(type + 1); + } + creators_[type] = creator; + return 0; +} + +void AutoCache::Bind(std::shared_ptr executor) +{ + if (executor == nullptr || taskId_ != Executor::INVALID_TASK_ID) { + return; + } + executor_ = executor; + taskId_ = executor_->Scheduler(std::chrono::steady_clock::now() + std::chrono::minutes(INTERVAL), + std::bind(&AutoCache::GarbageCollect, this, false), std::chrono::minutes(INTERVAL)); +} + +AutoCache::AutoCache() {} AutoCache::~AutoCache() { - stores_.EraseIf([](int32_t tokenId, std::map &stores) -> bool { - for (auto &[key, store] : stores) { - store.Close(); - } - return true; - }); + GarbageCollect(true); + if (executor_ != nullptr) { + executor_->Remove(taskId_, true); + } } AutoCache::Store AutoCache::GetStore(const StoreMetaData &meta, const Watchers &watchers) @@ -42,31 +67,63 @@ AutoCache::Store AutoCache::GetStore(const StoreMetaData &meta, const Watchers & return !stores.empty(); } auto result = stores.emplace(std::piecewise_construct, std::forward_as_tuple(meta.storeId), - std::forward_as_tuple(dbStore, watchers)); + std::forward_as_tuple(dbStore, watchers, atoi(meta.user.c_str()))); store = result.first->second; return !stores.empty(); }); - executor_->Scheduler(std::chrono::steady_clock::now() + std::chrono::minutes(INTERVAL), - std::bind(&AutoCache::GarbageCollect, this)); return store; } -int32_t AutoCache::RegCreator(int32_t type, Creator creator) +void AutoCache::CloseStore(uint32_t tokenId, const std::string &storeId) { - if (type >= creators_.size()) { - creators_.resize(type + 1); - } - creators_[type] = creator; - return 0; + stores_.ComputeIfPresent(tokenId, [&storeId](auto &key, std::map &delegates) { + auto it = delegates.find(storeId); + if (it != delegates.end()) { + it->second.Close(); + delegates.erase(it); + } + return !delegates.empty(); + }); } -void AutoCache::GarbageCollect() +void AutoCache::CloseExcept(const std::set &users) +{ + stores_.EraseIf([&users](const auto &tokenId, std::map &delegates) { + if (delegates.empty() || users.count(delegates.begin()->second.GetUser()) != 0) { + return delegates.empty(); + } + + for (auto it = delegates.begin(); it != delegates.end();) { + // if the kv store is BUSY we wait more INTERVAL minutes again + if (!it->second.Close()) { + ++it; + } else { + it = delegates.erase(it); + } + } + return delegates.empty(); + }); +} + +void AutoCache::SetObserver(uint32_t tokenId, const std::string &storeId, const AutoCache::Watchers &watchers) +{ + stores_.ComputeIfPresent(tokenId, [&storeId, &watchers](auto &key, auto &stores) { + ZLOGD("tokenId:0x%{public}x storeId:%{public}s observers:%{public}zu", key, storeId.c_str(), watchers.size()); + auto it = stores.find(storeId); + if (it != stores.end()) { + it->second.SetObservers(watchers); + } + return true; + }); +} + +void AutoCache::GarbageCollect(bool isForce) { auto current = std::chrono::steady_clock::now(); - stores_.EraseIf([¤t](auto &key, std::map &delegates) { + stores_.EraseIf([¤t, isForce](auto &key, std::map &delegates) { for (auto it = delegates.begin(); it != delegates.end();) { // if the kv store is BUSY we wait more INTERVAL minutes again - if ((it->second < current) && it->second.Close()) { + if ((isForce || it->second < current) && it->second.Close()) { it = delegates.erase(it); } else { ++it; @@ -74,13 +131,10 @@ void AutoCache::GarbageCollect() } return delegates.empty(); }); - if (!stores_.Empty()) { - executor_->Scheduler(current + std::chrono::minutes(INTERVAL), std::bind(&AutoCache::GarbageCollect, this)); - } } -AutoCache::Delegate::Delegate(GeneralStore *delegate, const Watchers &watchers) - : store_(delegate), watchers_(watchers) +AutoCache::Delegate::Delegate(GeneralStore *delegate, const Watchers &watchers, int32_t user) + : store_(delegate), watchers_(watchers), user_(user) { time_ = std::chrono::steady_clock::now() + std::chrono::minutes(INTERVAL); if (store_ != nullptr) { @@ -129,6 +183,11 @@ void AutoCache::Delegate::SetObservers(const AutoCache::Watchers &watchers) watchers_ = watchers; } +int32_t AutoCache::Delegate::GetUser() const +{ + return user_; +} + int32_t AutoCache::Delegate::OnChange(Origin origin, const std::string &id) { Watchers watchers; -- Gitee From 582526107836a7d8ed91fc31bbc1f7c3f17dc4aa Mon Sep 17 00:00:00 2001 From: zuojiangjiang Date: Thu, 13 Apr 2023 08:16:57 +0000 Subject: [PATCH 12/44] !20 update Merge pull request !20 from zuojiangjiang/cloud_dev --- .../framework/cloud/cloud_info.cpp | 30 +- .../framework/include/cloud/cloud_info.h | 9 +- .../service/cloud/cloud_service_impl.cpp | 34 ++- .../service/rdb/rdb_event.cpp | 24 +- .../service/rdb/rdb_event.h | 14 +- .../service/rdb/rdb_service_impl.cpp | 134 +++++++-- .../service/rdb/rdb_service_impl.h | 10 + .../service/rdb/rdb_service_stub.cpp | 78 +++-- .../service/rdb/rdb_service_stub.h | 8 +- .../service/rdb/rdb_syncer.cpp | 22 +- .../native/rdb/include/rdb_service_proxy.h | 5 + .../native/rdb/include/rdb_types_util.h | 5 + .../native/rdb/src/rdb_service_proxy.cpp | 268 +++++++----------- .../native/rdb/src/rdb_types_util.cpp | 10 + .../inner_api/rdb/include/rdb_service.h | 6 + .../inner_api/rdb/include/rdb_types.h | 7 + 16 files changed, 402 insertions(+), 262 deletions(-) diff --git a/datamgr_service/services/distributeddataservice/framework/cloud/cloud_info.cpp b/datamgr_service/services/distributeddataservice/framework/cloud/cloud_info.cpp index aff70ea7..1cca4c4f 100644 --- a/datamgr_service/services/distributeddataservice/framework/cloud/cloud_info.cpp +++ b/datamgr_service/services/distributeddataservice/framework/cloud/cloud_info.cpp @@ -59,19 +59,45 @@ bool CloudInfo::AppInfo::Unmarshal(const Serializable::json &node) std::string CloudInfo::GetKey() const { - return GetKey(INFO_PREFIX, { id, std::to_string(user), account }); + return GetKey(INFO_PREFIX, { std::to_string(user), id }); } std::map CloudInfo::GetSchemaKey() const { std::map keys; for (const auto &app : apps) { - const auto key = GetKey(SCHEMA_PREFIX, { id, std::to_string(user), account, app.bundleName }); + const auto key = GetKey(SCHEMA_PREFIX, { std::to_string(user), id, app.bundleName }); keys.insert_or_assign(app.bundleName, key); } return keys; } +bool CloudInfo::IsValid() const +{ + return !id.empty(); +} + +bool CloudInfo::IsExist(const std::string &appId) const +{ + for (const auto &app : apps) { + if (app.appId == appId) { + return true; + } + } + return false; +} + +void CloudInfo::DelApp(const std::string &appId) +{ + for (auto it = apps.begin(); it != apps.end();) { + if ((*it).appId == appId) { + it = apps.erase(it); + break; + } + it++; + } +} + std::string CloudInfo::GetPrefix(const std::initializer_list &fields) { return GetKey(INFO_PREFIX, fields).append(Constant::KEY_SEPARATOR); diff --git a/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_info.h b/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_info.h index 9148e8b2..89b09e86 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_info.h +++ b/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_info.h @@ -20,9 +20,10 @@ namespace OHOS::DistributedData { class API_EXPORT CloudInfo final : public Serializable { public: struct API_EXPORT AppInfo final : public Serializable { + static constexpr uint32_t CURRENT_VERSION = 0x04000001; std::string bundleName; std::string appId; - uint64_t version; + uint64_t version = CURRENT_VERSION; bool cloudSwitch = false; bool Marshal(json &node) const override; @@ -30,7 +31,6 @@ public: }; int32_t user = 0; std::string id = ""; - std::string account = ""; uint64_t totalSpace = 0; uint64_t remainSpace = 0; bool enableCloud = false; @@ -38,7 +38,10 @@ public: std::string GetKey() const; std::map GetSchemaKey() const; - static std::string GetPrefix(const std::initializer_list &fields); + bool IsValid() const; + bool IsExist(const std::string &appId) const; + void DelApp(const std::string &appId); + static std::string GetPrefix(const std::initializer_list &field); bool Marshal(json &node) const override; bool Unmarshal(const json &node) override; diff --git a/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.cpp b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.cpp index 81b3ebde..983ca503 100644 --- a/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.cpp +++ b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.cpp @@ -24,7 +24,7 @@ #include "eventcenter/event_center.h" #include "feature/feature_system.h" #include "ipc_skeleton.h" -#include "kvstore_utils.h" +#include "utils/anonymous.h" #include "log_print.h" #include "metadata/meta_data_manager.h" #include "rdb_event.h" @@ -48,13 +48,17 @@ CloudServiceImpl::Factory::~Factory() {} CloudServiceImpl::CloudServiceImpl() { EventCenter::GetInstance().Subscribe(RdbEvent::RDB_FEATURE_INIT, [this](const Event &event) { - auto &rdbEvent = static_cast(event); - auto user = AccountDelegate::GetInstance()->GetUserByToken(rdbEvent.GetTokenId()); - auto cloudInfo = CloudServer::GetInstance()->GetServerInfo(user); - if (cloudInfo.id.empty()) { + auto instance = CloudServer::GetInstance(); + if (instance == nullptr) { ZLOGI("no cloud server"); return; } + auto &rdbEvent = static_cast(event); + auto cloudInfo = instance->GetServerInfo(rdbEvent.GetUser()); + if (!cloudInfo.IsValid()) { + ZLOGI("accountId empty"); + return; + } UpdateCloudInfo(cloudInfo); UpdateSchema(cloudInfo); }); @@ -138,11 +142,9 @@ int32_t CloudServiceImpl::GetCloudInfo(const std::string &id, CloudInfo &cloudIn cloudInfo.id = id; uint32_t tokenId = IPCSkeleton::GetCallingTokenID(); cloudInfo.user = AccountDelegate::GetInstance()->GetUserByToken(tokenId); - cloudInfo.account = AccountDelegate::GetInstance()->GetCurrentAccountId(); if (!MetaDataManager::GetInstance().LoadMeta(cloudInfo.GetKey(), cloudInfo, true)) { - ZLOGE("invalid argument id:%{public}s, user:%{public}d, account:%{public}s", - KvStoreUtils::ToBeAnonymous(cloudInfo.id).c_str(), cloudInfo.user, - KvStoreUtils::ToBeAnonymous(cloudInfo.account).c_str()); + ZLOGE("invalid argument id:%{public}s, user:%{public}d", + Anonymous::Change(cloudInfo.id).c_str(), cloudInfo.user); return ERROR; } return SUCCESS; @@ -172,5 +174,19 @@ void CloudServiceImpl::UpdateCloudInfo(DistributedData::CloudInfo &cloudInfo) void CloudServiceImpl::UpdateSchema(DistributedData::CloudInfo &cloudInfo) { + auto keys = cloudInfo.GetSchemaKey(); + for (const auto &key : keys) { + SchemaMeta schemaMeta; + if (MetaDataManager::GetInstance().LoadMeta(key.second, schemaMeta, true)) { + continue; + } + auto instance = CloudServer::GetInstance(); + if (instance == nullptr) { + ZLOGE("no cloud server"); + return; + } + schemaMeta = instance->GetAppSchema(cloudInfo.user, key.first); + MetaDataManager::GetInstance().SaveMeta(key.second, schemaMeta, true); + } } } \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_event.cpp b/datamgr_service/services/distributeddataservice/service/rdb/rdb_event.cpp index e968beb2..a80cca18 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_event.cpp +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_event.cpp @@ -16,13 +16,29 @@ #include "rdb_event.h" namespace OHOS::DistributedRdb { -RdbEvent::RdbEvent(int32_t evtId, uint32_t tokenId) - : DistributedData::Event(evtId), tokenId_(tokenId) +RdbEvent::RdbEvent(int32_t evtId, int32_t user, const std::string &bundleName, const std::string &storeName) + : DistributedData::Event(evtId), user_(user), bundleName_(std::move(bundleName)), storeName_(std::move(storeName)) { } -uint32_t RdbEvent::GetTokenId() const +int32_t RdbEvent::GetUser() const { - return tokenId_; + return user_; +} + +std::string RdbEvent::GetBundleName() const +{ + return bundleName_; +} + +std::string RdbEvent::GetStoreName() const +{ + return storeName_; +} + +bool RdbEvent::Equals(const DistributedData::Event &event) const +{ + auto &evt = static_cast(event); + return (user_ == evt.user_) && (bundleName_ == evt.bundleName_) && (storeName_ == evt.storeName_); } } \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_event.h b/datamgr_service/services/distributeddataservice/service/rdb/rdb_event.h index a70525a1..d3d83c33 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_event.h +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_event.h @@ -16,6 +16,7 @@ #ifndef OHOS_DISTRIBUTED_DATA_SERVICES_RDB_RDB_EVENT_H #define OHOS_DISTRIBUTED_DATA_SERVICES_RDB_RDB_EVENT_H +#include #include "eventcenter/event.h" namespace OHOS::DistributedRdb { @@ -27,12 +28,19 @@ public: RDB_BUTT }; - RdbEvent(int32_t evtId, uint32_t tokenId); + RdbEvent(int32_t evtId, int32_t user, const std::string &bundleName, const std::string &storeName); ~RdbEvent() = default; - uint32_t GetTokenId() const; + int32_t GetUser() const; + std::string GetBundleName() const; + std::string GetStoreName() const; + bool Equals(const DistributedData::Event &event) const override; private: - uint32_t tokenId_; + int32_t user_; + int32_t schemaVersion_; + std::string bundleName_; + std::string storeName_; + std::string cloudId_; }; } // namespace OHOS::DistributedRdb #endif // OHOS_DISTRIBUTED_DATA_SERVICES_RDB_RDB_EVENT_H diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.cpp b/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.cpp index a19ad18b..35a9fbf1 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.cpp +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.cpp @@ -17,6 +17,7 @@ #include "accesstoken_kit.h" #include "account/account_delegate.h" #include "checker/checker_manager.h" +#include "cloud/cloud_server.h" #include "communicator/device_manager_adapter.h" #include "crypto_manager.h" #include "eventcenter/event_center.h" @@ -140,16 +141,12 @@ void RdbServiceImpl::OnClientDied(pid_t pid) bool RdbServiceImpl::CheckAccess(const RdbSyncerParam ¶m) { - CheckerManager::StoreInfo storeInfo; - storeInfo.uid = IPCSkeleton::GetCallingUid(); - storeInfo.tokenId = IPCSkeleton::GetCallingTokenID(); - storeInfo.bundleName = param.bundleName_; - storeInfo.storeId = RdbSyncer::RemoveSuffix(param.storeName_); - auto instanceId = RdbSyncer::GetInstIndex(storeInfo.tokenId, storeInfo.bundleName); + auto tokenId = IPCSkeleton::GetCallingTokenID(); + auto instanceId = RdbSyncer::GetInstIndex(tokenId, param.bundleName_); if (instanceId != 0) { return false; } - return !CheckerManager::GetInstance().GetAppId(storeInfo).empty(); + return !GetAppId(param.bundleName_).empty(); } std::string RdbServiceImpl::ObtainDistributedTableName(const std::string &device, const std::string &table) @@ -169,7 +166,10 @@ int32_t RdbServiceImpl::InitNotifier(const RdbSyncerParam& param, const sptrGetUserByToken(token); - std::string appId = CheckerManager::GetInstance().GetAppId(storeInfo); + auto tokenId = IPCSkeleton::GetCallingTokenID(); + auto user = AccountDelegate::GetInstance()->GetUserByToken(tokenId); + std::string appId = GetAppId(param.bundleName_); std::string identifier = RelationalStoreManager::GetRelationalStoreIdentifier( - std::to_string(userId), appId, storeId); + std::to_string(user), appId, RdbSyncer::RemoveSuffix(param.storeName_)); return TransferStringToHex(identifier); } @@ -393,6 +390,109 @@ int32_t RdbServiceImpl::RemoteQuery(const RdbSyncerParam& param, const std::stri return syncer->RemoteQuery(device, sql, selectionArgs, resultSet); } +int32_t RdbServiceImpl::CloudConfig(const CloudParam ¶m, std::string &schema) +{ + if (!CheckAccess({.bundleName_ = param.bundleName, .storeName_ = param.storeName})) { + ZLOGE("permission error"); + return RDB_ERROR; + } + auto tokenId = IPCSkeleton::GetCallingTokenID(); + auto user = AccountDelegate::GetInstance()->GetUserByToken(tokenId); + if (ConfigCloudInfo(param, user) != RDB_OK) { + return RDB_ERROR; + } + auto createEvt = std::make_unique( + RdbEvent::RDB_CREATE, user, param.bundleName, RdbSyncer::RemoveSuffix(param.storeName)); + EventCenter::GetInstance().PostEvent(std::move(createEvt)); + if (GetSchema(param, user, schema) != RDB_OK) { + return RDB_ERROR; + } + return RDB_OK; +} + +int32_t RdbServiceImpl::GetSchema(const CloudParam ¶m, int32_t user, std::string &schema) +{ + CloudInfo cloudInfo; + cloudInfo.id = param.cloudId; + cloudInfo.user = user; + if (!MetaDataManager::GetInstance().LoadMeta(cloudInfo.GetKey(), cloudInfo, true)) { + ZLOGE("cloudId:%{public}s, user:%{public}d", param.cloudId.c_str(), user); + return RDB_ERROR; + } + auto appId = GetAppId(param.bundleName); + if (!cloudInfo.IsExist(appId)) { + ZLOGE("bundleName:%{public}s", param.bundleName.c_str()); + return RDB_ERROR; + } + SchemaMeta schemaMeta; + auto keys = cloudInfo.GetSchemaKey(); + if (!MetaDataManager::GetInstance().LoadMeta(keys[param.bundleName], schemaMeta, true)) { + ZLOGE("schema empty, bundleName:%{public}s", param.bundleName.c_str()); + return RDB_ERROR; + } + schema = Serializable::Marshall(schemaMeta); + return RDB_OK; +} + +int32_t RdbServiceImpl::ConfigCloudInfo(const CloudParam ¶m, int32_t user) +{ + CloudInfo cloudInfo; + cloudInfo.id = param.cloudId; + cloudInfo.user = user; + if (!MetaDataManager::GetInstance().LoadMeta(cloudInfo.GetKey(), cloudInfo, true)) { + auto instance = CloudServer::GetInstance(); + if (instance == nullptr) { + return RDB_ERROR; + } + cloudInfo = instance->GetServerInfo(user); + if (!cloudInfo.IsValid()) { + return RDB_ERROR; + } + } + auto appId = GetAppId(param.bundleName); + if (!cloudInfo.IsExist(appId)) { + CloudInfo::AppInfo appInfo; + appInfo.bundleName = param.bundleName; + appInfo.appId = appId; + cloudInfo.apps.emplace_back(appInfo); + } + MetaDataManager::GetInstance().SaveMeta(cloudInfo.GetKey(), cloudInfo, true); + return RDB_OK; +} + +int32_t RdbServiceImpl::ClearCloudConfig(const CloudParam ¶m) +{ + if (!CheckAccess({.bundleName_ = param.bundleName, .storeName_ = param.storeName})) { + ZLOGE("permission error"); + return RDB_ERROR; + } + auto tokenId = IPCSkeleton::GetCallingTokenID(); + CloudInfo cloudInfo; + cloudInfo.user = AccountDelegate::GetInstance()->GetUserByToken(tokenId); + cloudInfo.id = param.cloudId; + if (!MetaDataManager::GetInstance().LoadMeta(cloudInfo.GetKey(), cloudInfo, true)) { + ZLOGE("invalid argument id:%{public}s, user:%{public}d", + Anonymous::Change(cloudInfo.id).c_str(), cloudInfo.user); + return RDB_ERROR; + } + auto appId = GetAppId(param.bundleName); + if (cloudInfo.IsExist(appId)) { + auto keys = cloudInfo.GetSchemaKey(); + MetaDataManager::GetInstance().DelMeta(keys[param.bundleName], true); + cloudInfo.DelApp(appId); + } + return RDB_OK; +} + +std::string RdbServiceImpl::GetAppId(const std::string &bundleName) +{ + CheckerManager::StoreInfo storeInfo; + storeInfo.uid = IPCSkeleton::GetCallingUid(); + storeInfo.tokenId = IPCSkeleton::GetCallingTokenID(); + storeInfo.bundleName = bundleName; + return CheckerManager::GetInstance().GetAppId(storeInfo); +} + int32_t RdbServiceImpl::CreateRDBTable( const RdbSyncerParam ¶m, const std::string &writePermission, const std::string &readPermission) { @@ -451,9 +551,9 @@ int32_t RdbServiceImpl::DestroyRDBTable(const RdbSyncerParam ¶m) int32_t RdbServiceImpl::OnInitialize() { - EventCenter::Defer defer; auto tokenId = IPCSkeleton::GetCallingTokenID(); - auto initEvt = std::make_unique(RdbEvent::RDB_FEATURE_INIT, tokenId); + auto user = AccountDelegate::GetInstance()->GetUserByToken(tokenId); + auto initEvt = std::make_unique(RdbEvent::RDB_FEATURE_INIT, user, "", ""); EventCenter::GetInstance().PostEvent(std::move(initEvt)); return RDB_OK; } diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.h b/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.h index 3d2324bd..64792d8d 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.h +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.h @@ -69,6 +69,10 @@ protected: int32_t DoUnSubscribe(const RdbSyncerParam& param) override; + int32_t CloudConfig(const CloudParam ¶m, std::string &schema) override; + + int32_t ClearCloudConfig(const CloudParam ¶m) override; + private: std::string GenIdentifier(const RdbSyncerParam& param); @@ -80,6 +84,12 @@ private: void OnAsyncComplete(pid_t pid, uint32_t seqNum, const SyncResult& result); + int32_t ConfigCloudInfo(const CloudParam ¶m, int32_t user); + + int32_t GetSchema(const CloudParam ¶m, int32_t user, std::string &schema); + + std::string GetAppId(const std::string &bundleName); + class DeathRecipientImpl : public IRemoteObject::DeathRecipient { public: using DeathCallback = std::function; diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_stub.cpp b/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_stub.cpp index fc8a5472..de06ccf8 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_stub.cpp +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_stub.cpp @@ -44,19 +44,9 @@ int32_t RdbServiceStub::OnRemoteInitNotifier(MessageParcel &data, MessageParcel reply.WriteInt32(RDB_ERROR); return RDB_OK; } - if (notifier == nullptr) { - ZLOGE("notifier is null"); - reply.WriteInt32(RDB_ERROR); - return RDB_OK; - } - if (InitNotifier(param, notifier) != RDB_OK) { - ZLOGE("init notifier failed"); - reply.WriteInt32(RDB_ERROR); - return RDB_OK; - } - ZLOGI("success"); - reply.WriteInt32(RDB_OK); - return RDB_OK; + + auto status = InitNotifier(param, notifier); + return ITypesUtil::Marshal(reply, status) ? RDB_OK : RDB_ERROR; } int32_t RdbServiceStub::OnRemoteSetDistributedTables(MessageParcel &data, MessageParcel &reply) @@ -69,8 +59,8 @@ int32_t RdbServiceStub::OnRemoteSetDistributedTables(MessageParcel &data, Messag return RDB_OK; } - reply.WriteInt32(SetDistributedTables(param, tables)); - return RDB_OK; + auto status = SetDistributedTables(param, tables); + return ITypesUtil::Marshal(reply, status) ? RDB_OK : RDB_ERROR; } int32_t RdbServiceStub::OnRemoteDoSync(MessageParcel &data, MessageParcel &reply) @@ -85,15 +75,8 @@ int32_t RdbServiceStub::OnRemoteDoSync(MessageParcel &data, MessageParcel &reply } SyncResult result; - if (DoSync(param, option, predicates, result) != RDB_OK) { - reply.WriteInt32(RDB_ERROR); - return RDB_OK; - } - if (!ITypesUtil::Marshal(reply, result)) { - reply.WriteInt32(RDB_ERROR); - return RDB_OK; - } - return RDB_OK; + auto status = DoSync(param, option, predicates, result); + return ITypesUtil::Marshal(reply, status, result) ? RDB_OK : RDB_ERROR; } int32_t RdbServiceStub::OnRemoteDoAsync(MessageParcel &data, MessageParcel &reply) @@ -108,8 +91,8 @@ int32_t RdbServiceStub::OnRemoteDoAsync(MessageParcel &data, MessageParcel &repl return RDB_OK; } - reply.WriteInt32(DoAsync(param, seqNum, option, predicates)); - return RDB_OK; + auto status = DoAsync(param, seqNum, option, predicates); + return ITypesUtil::Marshal(reply, status) ? RDB_OK : RDB_ERROR; } int32_t RdbServiceStub::OnRemoteDoSubscribe(MessageParcel &data, MessageParcel &reply) @@ -150,13 +133,7 @@ int32_t RdbServiceStub::OnRemoteDoRemoteQuery(MessageParcel& data, MessageParcel sptr resultSet; int32_t status = RemoteQuery(param, device, sql, selectionArgs, resultSet); - if (status != RDB_OK) { - reply.WriteInt32(RDB_ERROR); - return RDB_OK; - } - reply.WriteInt32(RDB_OK); - reply.WriteRemoteObject(resultSet); - return RDB_OK; + return ITypesUtil::Marshal(reply, status, resultSet) ? RDB_OK : RDB_ERROR; } bool RdbServiceStub::CheckInterfaceToken(MessageParcel& data) @@ -194,12 +171,7 @@ int32_t RdbServiceStub::OnRemoteDoCreateTable(MessageParcel &data, MessageParcel } int32_t status = CreateRDBTable(param, writePermission, readPermission); - if (status != RDB_OK) { - reply.WriteInt32(RDB_ERROR); - return RDB_OK; - } - reply.WriteInt32(RDB_OK); - return RDB_OK; + return ITypesUtil::Marshal(reply, status) ? RDB_OK : RDB_ERROR; } int32_t RdbServiceStub::OnRemoteDoDestroyTable(MessageParcel &data, MessageParcel &reply) @@ -212,11 +184,33 @@ int32_t RdbServiceStub::OnRemoteDoDestroyTable(MessageParcel &data, MessageParce } int32_t status = DestroyRDBTable(param); - if (status != RDB_OK) { + return ITypesUtil::Marshal(reply, status) ? RDB_OK : RDB_ERROR; +} + +int32_t RdbServiceStub::OnRemoteDoCloudConfig(MessageParcel& data, MessageParcel& reply) +{ + CloudParam param; + if (!ITypesUtil::Unmarshal(data, param)) { + ZLOGE("read from message parcel failed"); reply.WriteInt32(RDB_ERROR); return RDB_OK; } - reply.WriteInt32(RDB_OK); - return RDB_OK; + + std::string schema; + int32_t status = CloudConfig(param, schema); + return ITypesUtil::Marshal(reply, status, schema) ? RDB_OK : RDB_ERROR; +} + +int32_t RdbServiceStub::OnRemoteDoClearCloudConfig(MessageParcel& data, MessageParcel& reply) +{ + CloudParam param; + if (!ITypesUtil::Unmarshal(data, param)) { + ZLOGE("read from message parcel failed"); + reply.WriteInt32(RDB_ERROR); + return RDB_OK; + } + + int32_t status = ClearCloudConfig(param); + return ITypesUtil::Marshal(reply, status) ? RDB_OK : RDB_ERROR; } } // namespace OHOS::DistributedRdb diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_stub.h b/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_stub.h index 901a7d6e..49599de2 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_stub.h +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_stub.h @@ -68,6 +68,10 @@ private: int32_t OnRemoteDoDestroyTable(MessageParcel& data, MessageParcel& reply); + int32_t OnRemoteDoCloudConfig(MessageParcel& data, MessageParcel& reply); + + int32_t OnRemoteDoClearCloudConfig(MessageParcel& data, MessageParcel& reply); + using RequestHandle = int (RdbServiceStub::*)(MessageParcel &, MessageParcel &); static constexpr RequestHandle HANDLERS[RDB_SERVICE_CMD_MAX] = { [RDB_SERVICE_CMD_OBTAIN_TABLE] = &RdbServiceStub::OnRemoteObtainDistributedTableName, @@ -79,7 +83,9 @@ private: [RDB_SERVICE_CMD_UNSUBSCRIBE] = &RdbServiceStub::OnRemoteDoUnSubscribe, [RDB_SERVICE_CMD_REMOTE_QUERY] = &RdbServiceStub::OnRemoteDoRemoteQuery, [RDB_SERVICE_CREATE_RDB_TABLE] = &RdbServiceStub::OnRemoteDoCreateTable, - [RDB_SERVICE_DESTROY_RDB_TABLE] = &RdbServiceStub::OnRemoteDoDestroyTable + [RDB_SERVICE_DESTROY_RDB_TABLE] = &RdbServiceStub::OnRemoteDoDestroyTable, + [RDB_SERVICE_CLOUD_CONFIG] = &RdbServiceStub::OnRemoteDoCloudConfig, + [RDB_SERVICE_CLEAR_CLOUD_CONFIG] = &RdbServiceStub::OnRemoteDoClearCloudConfig }; }; } // namespace OHOS::DistributedRdb diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_syncer.cpp b/datamgr_service/services/distributeddataservice/service/rdb/rdb_syncer.cpp index 1bd74d45..0e6fc39c 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_syncer.cpp +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_syncer.cpp @@ -428,10 +428,11 @@ int32_t RdbSyncer::DoSync(const SyncOption &option, const RdbPredicates &predica } ZLOGI("delegate sync"); - return delegate->Sync(devices, static_cast(option.mode), - MakeQuery(predicates), [&result] (const auto& syncStatus) { - HandleSyncStatus(syncStatus, result); - }, true); + auto status = delegate->Sync(devices, static_cast(option.mode), + MakeQuery(predicates), [&result] (const auto& syncStatus) { + HandleSyncStatus(syncStatus, result); + }, true); + return status == DistributedDB::DBStatus::OK ? RDB_OK : RDB_ERROR; } int32_t RdbSyncer::DoAsync(const SyncOption &option, const RdbPredicates &predicates, const SyncCallback& callback) @@ -450,12 +451,13 @@ int32_t RdbSyncer::DoAsync(const SyncOption &option, const RdbPredicates &predic } ZLOGI("delegate sync"); - return delegate->Sync(devices, static_cast(option.mode), - MakeQuery(predicates), [callback] (const auto& syncStatus) { - SyncResult result; - HandleSyncStatus(syncStatus, result); - callback(result); - }, false); + auto status = delegate->Sync(devices, static_cast(option.mode), + MakeQuery(predicates), [callback] (const auto& syncStatus) { + SyncResult result; + HandleSyncStatus(syncStatus, result); + callback(result); + }, false); + return status == DistributedDB::DBStatus::OK ? RDB_OK : RDB_ERROR; } int32_t RdbSyncer::RemoteQuery(const std::string& device, const std::string& sql, diff --git a/relational_store/frameworks/native/rdb/include/rdb_service_proxy.h b/relational_store/frameworks/native/rdb/include/rdb_service_proxy.h index 24651ee6..333616f0 100644 --- a/relational_store/frameworks/native/rdb/include/rdb_service_proxy.h +++ b/relational_store/frameworks/native/rdb/include/rdb_service_proxy.h @@ -67,6 +67,10 @@ protected: int32_t DoUnSubscribe(const RdbSyncerParam& param) override; + int32_t CloudConfig(const CloudParam& param, std::string &schema) override; + + int32_t ClearCloudConfig(const CloudParam& param) override; + private: uint32_t GetSeqNum(); @@ -88,6 +92,7 @@ private: ObserverMap observers_; sptr notifier_; + sptr remote_; static inline BrokerDelegator delegator_; }; } // namespace OHOS::DistributedRdb diff --git a/relational_store/frameworks/native/rdb/include/rdb_types_util.h b/relational_store/frameworks/native/rdb/include/rdb_types_util.h index 71dcf135..ca589d37 100644 --- a/relational_store/frameworks/native/rdb/include/rdb_types_util.h +++ b/relational_store/frameworks/native/rdb/include/rdb_types_util.h @@ -21,6 +21,7 @@ #include "values_bucket.h" #include "rdb_visibility.h" namespace OHOS::ITypesUtil { +using CloudParam = DistributedRdb::CloudParam; using SyncerParam = DistributedRdb::RdbSyncerParam; using SyncOption = DistributedRdb::SyncOption; using RdbPredicates = DistributedRdb::RdbPredicates; @@ -56,5 +57,9 @@ template<> bool Marshalling(const Asset &input, MessageParcel &data); template<> bool Unmarshalling(Asset &output, MessageParcel &data); +template<> +bool Marshalling(const CloudParam &input, MessageParcel &data); +template<> +bool Unmarshalling(CloudParam &output, MessageParcel &data); } #endif // DISTRIBUTED_RDB_RDB_TYPES_UTIL_H diff --git a/relational_store/frameworks/native/rdb/src/rdb_service_proxy.cpp b/relational_store/frameworks/native/rdb/src/rdb_service_proxy.cpp index 3554b6a9..a8f00b9d 100644 --- a/relational_store/frameworks/native/rdb/src/rdb_service_proxy.cpp +++ b/relational_store/frameworks/native/rdb/src/rdb_service_proxy.cpp @@ -20,9 +20,35 @@ #include "log_print.h" namespace OHOS::DistributedRdb { +#define IPC_SEND(code, reply, ...) \ +({ \ + int32_t __status = RDB_OK; \ + do { \ + MessageParcel request; \ + if (!request.WriteInterfaceToken(GetDescriptor())) { \ + __status = RDB_ERROR; \ + break; \ + } \ + if (!ITypesUtil::Marshal(request, ##__VA_ARGS__)) { \ + __status = RDB_ERROR; \ + break; \ + } \ + MessageOption option; \ + auto result = remote_->SendRequest((code), request, reply, option); \ + if (result != 0) { \ + __status = RDB_ERROR; \ + break; \ + } \ + \ + ITypesUtil::Unmarshal(reply, __status); \ + } while (0); \ + __status; \ +}) + RdbServiceProxy::RdbServiceProxy(const sptr &object) : IRemoteProxy(object) { + remote_ = Remote(); } void RdbServiceProxy::OnSyncComplete(uint32_t seqNum, const SyncResult &result) @@ -48,20 +74,10 @@ void RdbServiceProxy::OnDataChange(const std::string& storeName, const std::vect std::string RdbServiceProxy::ObtainDistributedTableName(const std::string &device, const std::string &table) { - MessageParcel data; - if (!data.WriteInterfaceToken(IRdbService::GetDescriptor())) { - ZLOGE("write descriptor failed"); - return ""; - } - if (!ITypesUtil::Marshal(data, device, table)) { - ZLOGE("write to message parcel failed"); - return ""; - } - MessageParcel reply; - MessageOption option; - if (Remote()->SendRequest(RDB_SERVICE_CMD_OBTAIN_TABLE, data, reply, option) != 0) { - ZLOGE("send request failed"); + int32_t status = IPC_SEND(RDB_SERVICE_CMD_OBTAIN_TABLE, reply, device, table); + if (status != RDB_OK) { + ZLOGE("status:%{public}d, device:%{public}.6s, table:%{public}s", status, device.c_str(), table.c_str()); return ""; } return reply.ReadString(); @@ -93,25 +109,13 @@ int32_t RdbServiceProxy::InitNotifier(const RdbSyncerParam& param) int32_t RdbServiceProxy::InitNotifier(const RdbSyncerParam ¶m, const sptr notifier) { - MessageParcel data; - if (!data.WriteInterfaceToken(IRdbService::GetDescriptor())) { - ZLOGE("write descriptor failed"); - return RDB_ERROR; - } - if (!ITypesUtil::Marshal(data, param, notifier)) { - ZLOGE("write to message parcel failed"); - return RDB_ERROR; - } - MessageParcel reply; - MessageOption option; - if (Remote()->SendRequest(RDB_SERVICE_CMD_INIT_NOTIFIER, data, reply, option) != 0) { - ZLOGE("send request failed"); - return RDB_ERROR; + int32_t status = IPC_SEND(RDB_SERVICE_CMD_INIT_NOTIFIER, reply, param, notifier); + if (status != RDB_OK) { + ZLOGE("status:%{public}d, bundleName:%{public}s, storeName:%{public}s", + status, param.bundleName_.c_str(), param.storeName_.c_str()); } - - int32_t res = RDB_ERROR; - return reply.ReadInt32(res) ? res : RDB_ERROR; + return status; } uint32_t RdbServiceProxy::GetSeqNum() @@ -122,21 +126,12 @@ uint32_t RdbServiceProxy::GetSeqNum() int32_t RdbServiceProxy::DoSync(const RdbSyncerParam& param, const SyncOption &option, const RdbPredicates &predicates, SyncResult& result) { - MessageParcel data; - if (!data.WriteInterfaceToken(IRdbService::GetDescriptor())) { - ZLOGE("write descriptor failed"); - return RDB_ERROR; - } - if (!ITypesUtil::Marshal(data, param, option, predicates)) { - ZLOGE("write to message parcel failed"); - return RDB_ERROR; - } - MessageParcel reply; - MessageOption opt; - if (Remote()->SendRequest(RDB_SERVICE_CMD_SYNC, data, reply, opt) != 0) { - ZLOGE("send request failed"); - return RDB_ERROR; + int32_t status = IPC_SEND(RDB_SERVICE_CMD_SYNC, reply, param, option, predicates); + if (status != RDB_OK) { + ZLOGE("status:%{public}d, bundleName:%{public}s, storeName:%{public}s", + status, param.bundleName_.c_str(), param.storeName_.c_str()); + return status; } if (!ITypesUtil::Unmarshal(reply, result)) { @@ -165,25 +160,13 @@ int32_t RdbServiceProxy::DoSync(const RdbSyncerParam& param, const SyncOption &o int32_t RdbServiceProxy::DoAsync(const RdbSyncerParam& param, uint32_t seqNum, const SyncOption &option, const RdbPredicates &predicates) { - MessageParcel data; - if (!data.WriteInterfaceToken(IRdbService::GetDescriptor())) { - ZLOGE("write descriptor failed"); - return RDB_ERROR; - } - if (!ITypesUtil::Marshal(data, param, seqNum, option, predicates)) { - ZLOGE("write to message parcel failed"); - return RDB_ERROR; - } - MessageParcel reply; - MessageOption opt; - if (Remote()->SendRequest(RDB_SERVICE_CMD_ASYNC, data, reply, opt) != 0) { - ZLOGE("send request failed"); - return RDB_ERROR; + int32_t status = IPC_SEND(RDB_SERVICE_CMD_ASYNC, reply, param, seqNum, option, predicates); + if (status != RDB_OK) { + ZLOGE("status:%{public}d, bundleName:%{public}s, storeName:%{public}s, seqNum:%{public}u", + status, param.bundleName_.c_str(), param.storeName_.c_str(), seqNum); } - - int32_t res = RDB_ERROR; - return reply.ReadInt32(res) ? res : RDB_ERROR; + return status; } int32_t RdbServiceProxy::DoAsync(const RdbSyncerParam& param, const SyncOption &option, @@ -208,25 +191,13 @@ int32_t RdbServiceProxy::DoAsync(const RdbSyncerParam& param, const SyncOption & int32_t RdbServiceProxy::SetDistributedTables(const RdbSyncerParam& param, const std::vector &tables) { - MessageParcel data; - if (!data.WriteInterfaceToken(IRdbService::GetDescriptor())) { - ZLOGE("write descriptor failed"); - return RDB_ERROR; - } - if (!ITypesUtil::Marshal(data, param, tables)) { - ZLOGE("write to message parcel failed"); - return RDB_ERROR; - } - MessageParcel reply; - MessageOption option; - if (Remote()->SendRequest(RDB_SERVICE_CMD_SET_DIST_TABLE, data, reply, option) != 0) { - ZLOGE("send request failed"); - return RDB_ERROR; + int32_t status = IPC_SEND(RDB_SERVICE_CMD_SET_DIST_TABLE, reply, param, tables); + if (status != RDB_OK) { + ZLOGE("status:%{public}d, bundleName:%{public}s, storeName:%{public}s", + status, param.bundleName_.c_str(), param.storeName_.c_str()); } - - int32_t res = RDB_ERROR; - return reply.ReadInt32(res) ? res : RDB_ERROR; + return status; } int32_t RdbServiceProxy::Sync(const RdbSyncerParam& param, const SyncOption &option, @@ -276,25 +247,13 @@ int32_t RdbServiceProxy::Subscribe(const RdbSyncerParam ¶m, const SubscribeO int32_t RdbServiceProxy::DoSubscribe(const RdbSyncerParam ¶m) { - MessageParcel data; - if (!data.WriteInterfaceToken(IRdbService::GetDescriptor())) { - ZLOGE("write descriptor failed"); - return RDB_ERROR; - } - if (!ITypesUtil::Marshal(data, param)) { - ZLOGE("write to message parcel failed"); - return RDB_ERROR; - } - MessageParcel reply; - MessageOption option; - if (Remote()->SendRequest(RDB_SERVICE_CMD_SUBSCRIBE, data, reply, option) != 0) { - ZLOGE("send request failed"); - return RDB_ERROR; + int32_t status = IPC_SEND(RDB_SERVICE_CMD_SUBSCRIBE, reply, param); + if (status != RDB_OK) { + ZLOGE("status:%{public}d, bundleName:%{public}s, storeName:%{public}s", + status, param.bundleName_.c_str(), param.storeName_.c_str()); } - - int32_t res = RDB_ERROR; - return reply.ReadInt32(res) ? res : RDB_ERROR; + return status; } int32_t RdbServiceProxy::UnSubscribe(const RdbSyncerParam ¶m, const SubscribeOption &option, @@ -314,50 +273,47 @@ int32_t RdbServiceProxy::UnSubscribe(const RdbSyncerParam ¶m, const Subscrib int32_t RdbServiceProxy::DoUnSubscribe(const RdbSyncerParam ¶m) { - MessageParcel data; - if (!data.WriteInterfaceToken(IRdbService::GetDescriptor())) { - ZLOGE("write descriptor failed"); - return RDB_ERROR; - } - if (!ITypesUtil::Marshal(data, param)) { - ZLOGE("write to message parcel failed"); - return RDB_ERROR; + MessageParcel reply; + int32_t status = IPC_SEND(RDB_SERVICE_CMD_UNSUBSCRIBE, reply, param); + if (status != RDB_OK) { + ZLOGE("status:%{public}d, bundleName:%{public}s, storeName:%{public}s", + status, param.bundleName_.c_str(), param.storeName_.c_str()); } + return status; +} +int32_t RdbServiceProxy::CloudConfig(const CloudParam ¶m, std::string &schema) +{ MessageParcel reply; - MessageOption option; - if (Remote()->SendRequest(RDB_SERVICE_CMD_UNSUBSCRIBE, data, reply, option) != 0) { - ZLOGE("send request failed"); - return RDB_ERROR; + int32_t status = IPC_SEND(RDB_SERVICE_CLOUD_CONFIG, reply, param); + if (status != RDB_OK) { + ZLOGE("status:%{public}d, bundleName:%{public}s, storeName:%{public}s, cloudId:%{public}.6s", + status, param.bundleName.c_str(), param.storeName.c_str(), param.cloudId.c_str()); + return status; } + ITypesUtil::Unmarshal(reply, schema); + return RDB_OK; +} - int32_t res = RDB_ERROR; - return reply.ReadInt32(res) ? res : RDB_ERROR; +int32_t RdbServiceProxy::ClearCloudConfig(const CloudParam ¶m) +{ + MessageParcel reply; + int32_t status = IPC_SEND(RDB_SERVICE_CLEAR_CLOUD_CONFIG, reply, param); + if (status != RDB_OK) { + ZLOGE("status:%{public}d, bundleName:%{public}s, storeName:%{public}s, cloudId:%{public}.6s", + status, param.bundleName.c_str(), param.storeName.c_str(), param.cloudId.c_str()); + } + return status; } int32_t RdbServiceProxy::RemoteQuery(const RdbSyncerParam& param, const std::string& device, const std::string& sql, const std::vector& selectionArgs, sptr& resultSet) { - MessageParcel data; - if (!data.WriteInterfaceToken(IRdbService::GetDescriptor())) { - ZLOGE("write descriptor failed"); - return RDB_ERROR; - } - if (!ITypesUtil::Marshal(data, param, device, sql, selectionArgs)) { - ZLOGE("write to message parcel failed"); - return RDB_ERROR; - } - MessageParcel reply; - MessageOption option; - if (Remote()->SendRequest(RDB_SERVICE_CMD_REMOTE_QUERY, data, reply, option) != 0) { - ZLOGE("send request failed"); - return RDB_ERROR; - } - - int32_t status = reply.ReadInt32(); - if (status != RdbStatus::RDB_OK) { - ZLOGE("remote query failed, server side status is %{public}d", status); + int32_t status = IPC_SEND(RDB_SERVICE_CMD_REMOTE_QUERY, reply, param, device, sql, selectionArgs); + if (status != RDB_OK) { + ZLOGE("status:%{public}d, bundleName:%{public}s, storeName:%{public}s, device:%{public}.6s", + status, param.bundleName_.c_str(), param.storeName_.c_str(), device.c_str()); return status; } @@ -389,55 +345,25 @@ void RdbServiceProxy::ImportObservers(ObserverMap &observers) int32_t RdbServiceProxy::CreateRDBTable( const RdbSyncerParam ¶m, const std::string &writePermission, const std::string &readPermission) { - MessageParcel data; - if (!data.WriteInterfaceToken(IRdbService::GetDescriptor())) { - ZLOGE("write descriptor failed"); - return RDB_ERROR; - } - if (!ITypesUtil::Marshal(data, param, writePermission, readPermission)) { - ZLOGE("write to message parcel failed"); - return RDB_ERROR; - } - MessageParcel reply; - MessageOption option; - if (Remote()->SendRequest(RDB_SERVICE_CREATE_RDB_TABLE, data, reply, option) != 0) { - ZLOGE("send request failed"); - return RDB_ERROR; - } - - int32_t status = reply.ReadInt32(); - if (status != RdbStatus::RDB_OK) { - ZLOGE("remote query failed, server side status is %{public}d", status); - return status; - } - return RDB_OK; + int32_t status = IPC_SEND(RDB_SERVICE_CREATE_RDB_TABLE, reply, param, writePermission, readPermission); + if (status != RDB_OK) { + ZLOGE("status:%{public}d, bundleName:%{public}s, storeName:%{public}s," + "writePermission:%{public}.6s, readPermission:%{public}.6s", + status, param.bundleName_.c_str(), param.storeName_.c_str(), + writePermission.c_str(), readPermission.c_str()); + } + return status; } int32_t RdbServiceProxy::DestroyRDBTable(const RdbSyncerParam ¶m) { - MessageParcel data; - if (!data.WriteInterfaceToken(IRdbService::GetDescriptor())) { - ZLOGE("write descriptor failed"); - return RDB_ERROR; - } - if (!ITypesUtil::Marshal(data, param)) { - ZLOGE("write to message parcel failed"); - return RDB_ERROR; - } - MessageParcel reply; - MessageOption option; - if (Remote()->SendRequest(RDB_SERVICE_DESTROY_RDB_TABLE, data, reply, option) != 0) { - ZLOGE("send request failed"); - return RDB_ERROR; + int32_t status = IPC_SEND(RDB_SERVICE_DESTROY_RDB_TABLE, reply, param); + if (status != RDB_OK) { + ZLOGE("status:%{public}d, bundleName:%{public}s, storeName:%{public}s", + status, param.bundleName_.c_str(), param.storeName_.c_str()); } - - int32_t status = reply.ReadInt32(); - if (status != RdbStatus::RDB_OK) { - ZLOGE("remote query failed, server side status is %{public}d", status); - return status; - } - return RDB_OK; + return status; } } // namespace OHOS::DistributedRdb diff --git a/relational_store/frameworks/native/rdb/src/rdb_types_util.cpp b/relational_store/frameworks/native/rdb/src/rdb_types_util.cpp index 7a2fde1c..d7ed7c9e 100644 --- a/relational_store/frameworks/native/rdb/src/rdb_types_util.cpp +++ b/relational_store/frameworks/native/rdb/src/rdb_types_util.cpp @@ -98,4 +98,14 @@ bool ITypesUtil::Unmarshalling(Asset &output, MessageParcel &data) { return ITypesUtil::Unmarshal(data, output.version, output.name, output.size, output.modifyTime, output.uri); } +template<> +bool Marshalling(const CloudParam &input, MessageParcel &data) +{ + return ITypesUtil::Marshal(data, input.bundleName, input.storeName, input.cloudId, input.schemaVerion); +} +template<> +bool Unmarshalling(CloudParam &output, MessageParcel &data) +{ + return ITypesUtil::Unmarshal(data, output.bundleName, output.storeName, output.cloudId, output.schemaVerion); +} } \ No newline at end of file diff --git a/relational_store/interfaces/inner_api/rdb/include/rdb_service.h b/relational_store/interfaces/inner_api/rdb/include/rdb_service.h index a72ebf72..bffb1ac3 100644 --- a/relational_store/interfaces/inner_api/rdb/include/rdb_service.h +++ b/relational_store/interfaces/inner_api/rdb/include/rdb_service.h @@ -37,6 +37,8 @@ public: RDB_SERVICE_CMD_REMOTE_QUERY, RDB_SERVICE_CREATE_RDB_TABLE, RDB_SERVICE_DESTROY_RDB_TABLE, + RDB_SERVICE_CLOUD_CONFIG, + RDB_SERVICE_CLEAR_CLOUD_CONFIG, RDB_SERVICE_CMD_MAX }; virtual std::string ObtainDistributedTableName(const std::string &device, const std::string &table) = 0; @@ -71,6 +73,10 @@ protected: virtual int32_t DoSubscribe(const RdbSyncerParam ¶m) = 0; virtual int32_t DoUnSubscribe(const RdbSyncerParam ¶m) = 0; + + virtual int32_t CloudConfig(const CloudParam ¶m, std::string &schema) = 0; + + virtual int32_t ClearCloudConfig(const CloudParam ¶m) = 0; }; } } // namespace OHOS::DistributedRdb diff --git a/relational_store/interfaces/inner_api/rdb/include/rdb_types.h b/relational_store/interfaces/inner_api/rdb/include/rdb_types.h index 2dfc6044..14934409 100644 --- a/relational_store/interfaces/inner_api/rdb/include/rdb_types.h +++ b/relational_store/interfaces/inner_api/rdb/include/rdb_types.h @@ -48,6 +48,13 @@ struct RdbSyncerParam { }; }; +struct CloudParam { + std::string bundleName; + std::string storeName; + std::string cloudId; + int32_t schemaVerion; +}; + enum SyncMode { PUSH, PULL, -- Gitee From a1f36635f8673fcd2edb3da16dd13d390dcdf049 Mon Sep 17 00:00:00 2001 From: Sven Wang Date: Fri, 14 Apr 2023 17:42:57 +0800 Subject: [PATCH 13/44] update Signed-off-by: Sven Wang --- .../framework/cloud/schema_meta.cpp | 4 ++-- .../framework/include/cloud/schema_meta.h | 2 +- .../interfaces/inner_api/rdb/include/value_object.h | 11 +---------- 3 files changed, 4 insertions(+), 13 deletions(-) diff --git a/datamgr_service/services/distributeddataservice/framework/cloud/schema_meta.cpp b/datamgr_service/services/distributeddataservice/framework/cloud/schema_meta.cpp index 8fe8f41b..ebd32b6e 100644 --- a/datamgr_service/services/distributeddataservice/framework/cloud/schema_meta.cpp +++ b/datamgr_service/services/distributeddataservice/framework/cloud/schema_meta.cpp @@ -46,14 +46,14 @@ bool SchemaMeta::Database::Unmarshal(const Serializable::json &node) bool SchemaMeta::Table::Marshal(Serializable::json &node) const { SetValue(node[GET_NAME(name)], name); - SetValue(node[GET_NAME(type)], type); + SetValue(node[GET_NAME(fields)], fields); return true; } bool SchemaMeta::Table::Unmarshal(const Serializable::json &node) { GetValue(node, GET_NAME(name), name); - GetValue(node, GET_NAME(type), type); + GetValue(node, GET_NAME(fields), fields); return true; } diff --git a/datamgr_service/services/distributeddataservice/framework/include/cloud/schema_meta.h b/datamgr_service/services/distributeddataservice/framework/include/cloud/schema_meta.h index d2fd0701..6d1939e6 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/cloud/schema_meta.h +++ b/datamgr_service/services/distributeddataservice/framework/include/cloud/schema_meta.h @@ -30,7 +30,7 @@ public: struct API_EXPORT Table final : public Serializable { std::string name; - std::vector type; + std::vector fields; bool Marshal(json &node) const override; bool Unmarshal(const json &node) override; }; diff --git a/relational_store/interfaces/inner_api/rdb/include/value_object.h b/relational_store/interfaces/inner_api/rdb/include/value_object.h index ae4e7677..cbd10dfc 100644 --- a/relational_store/interfaces/inner_api/rdb/include/value_object.h +++ b/relational_store/interfaces/inner_api/rdb/include/value_object.h @@ -300,16 +300,7 @@ private: int Get(T &output) const; template - struct index_of : std::integral_constant { - }; - - template - inline static constexpr size_t index_of_v = index_of<_Tp, _Types...>::value; - - template - struct index_of<_Tp, _First, _Rest...> - : std::integral_constant ? 0 : index_of_v<_Tp, _Rest...> + 1> { - }; + inline static constexpr size_t index_of_v = std::__detail::__variant::__index_of_v<_Tp, _Types...>; template static std::enable_if_t<(index_of_v<_T, _Rest...> < sizeof...(_Rest)), const _T *> GetIf( -- Gitee From 3acdcbfa7060aca78982f63e9fcd6140d9c560c5 Mon Sep 17 00:00:00 2001 From: zuojiangjiang Date: Fri, 14 Apr 2023 10:26:22 +0000 Subject: [PATCH 14/44] !21 update Merge pull request !21 from zuojiangjiang/cloud_dev --- .../cloud/cloud_event.cpp} | 25 +-- .../framework/cloud/cloud_info.cpp | 10 + .../framework/cloud/schema_meta.cpp | 10 + .../include/cloud/cloud_event.h} | 27 +-- .../framework/include/cloud/cloud_info.h | 6 +- .../framework/include/cloud/schema_meta.h | 3 +- .../framework/include/eventcenter/event.h | 2 +- .../service/cloud/cloud_service_impl.cpp | 203 ++++++++++++++---- .../service/cloud/cloud_service_impl.h | 19 +- .../service/cloud/cloud_service_stub.cpp | 25 +++ .../service/cloud/cloud_service_stub.h | 2 + .../service/rdb/rdb_service_impl.cpp | 99 +-------- .../service/rdb/rdb_service_impl.h | 8 - .../service/rdb/rdb_service_stub.cpp | 27 --- .../service/rdb/rdb_service_stub.h | 8 +- .../cloud_data/include/cloud_service_proxy.h | 4 +- .../cloud_data/include/cloud_types_util.h | 30 +++ .../cloud_data/src/cloud_service_proxy.cpp | 23 ++ .../cloud_data/src/cloud_types_util.cpp | 30 +++ .../native/rdb/include/rdb_service_proxy.h | 4 - .../native/rdb/include/rdb_types_util.h | 5 - .../native/rdb/src/rdb_service_proxy.cpp | 24 --- .../native/rdb/src/rdb_types_util.cpp | 10 - .../cloud_data/include/cloud_service.h | 11 + .../inner_api/rdb/include/rdb_service.h | 6 - 25 files changed, 350 insertions(+), 271 deletions(-) rename datamgr_service/services/distributeddataservice/{service/rdb/rdb_event.cpp => framework/cloud/cloud_event.cpp} (48%) rename datamgr_service/services/distributeddataservice/{service/rdb/rdb_event.h => framework/include/cloud/cloud_event.h} (54%) create mode 100644 relational_store/frameworks/native/cloud_data/include/cloud_types_util.h create mode 100644 relational_store/frameworks/native/cloud_data/src/cloud_types_util.cpp diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_event.cpp b/datamgr_service/services/distributeddataservice/framework/cloud/cloud_event.cpp similarity index 48% rename from datamgr_service/services/distributeddataservice/service/rdb/rdb_event.cpp rename to datamgr_service/services/distributeddataservice/framework/cloud/cloud_event.cpp index a80cca18..66e58e6d 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_event.cpp +++ b/datamgr_service/services/distributeddataservice/framework/cloud/cloud_event.cpp @@ -13,32 +13,21 @@ * limitations under the License. */ -#include "rdb_event.h" +#include "cloud/cloud_event.h" -namespace OHOS::DistributedRdb { -RdbEvent::RdbEvent(int32_t evtId, int32_t user, const std::string &bundleName, const std::string &storeName) - : DistributedData::Event(evtId), user_(user), bundleName_(std::move(bundleName)), storeName_(std::move(storeName)) +namespace OHOS::DistributedData { +CloudEvent::CloudEvent(int32_t evtId, int32_t user) + : Event(evtId), user_(user) { } -int32_t RdbEvent::GetUser() const +int32_t CloudEvent::GetUser() const { return user_; } -std::string RdbEvent::GetBundleName() const +bool CloudEvent::Equals(const Event &event) const { - return bundleName_; -} - -std::string RdbEvent::GetStoreName() const -{ - return storeName_; -} - -bool RdbEvent::Equals(const DistributedData::Event &event) const -{ - auto &evt = static_cast(event); - return (user_ == evt.user_) && (bundleName_ == evt.bundleName_) && (storeName_ == evt.storeName_); + return false; } } \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/framework/cloud/cloud_info.cpp b/datamgr_service/services/distributeddataservice/framework/cloud/cloud_info.cpp index 1cca4c4f..c0b0ccc8 100644 --- a/datamgr_service/services/distributeddataservice/framework/cloud/cloud_info.cpp +++ b/datamgr_service/services/distributeddataservice/framework/cloud/cloud_info.cpp @@ -98,6 +98,16 @@ void CloudInfo::DelApp(const std::string &appId) } } +CloudInfo::AppInfo &CloudInfo::GetApp(const std::string &appId) +{ + for (auto &app : apps) { + if (app.appId == appId) { + return app; + } + } + return appNil_; +} + std::string CloudInfo::GetPrefix(const std::initializer_list &fields) { return GetKey(INFO_PREFIX, fields).append(Constant::KEY_SEPARATOR); diff --git a/datamgr_service/services/distributeddataservice/framework/cloud/schema_meta.cpp b/datamgr_service/services/distributeddataservice/framework/cloud/schema_meta.cpp index ebd32b6e..e8787106 100644 --- a/datamgr_service/services/distributeddataservice/framework/cloud/schema_meta.cpp +++ b/datamgr_service/services/distributeddataservice/framework/cloud/schema_meta.cpp @@ -74,4 +74,14 @@ bool SchemaMeta::Field::Unmarshal(const Serializable::json &node) GetValue(node, GET_NAME(nullable), nullable); return true; } + +SchemaMeta::Database SchemaMeta::GetDataBase(const std::string &storeId) +{ + for (const auto &database : databases) { + if (database.name == storeId) { + return database; + } + } + return {}; +} } // namespace OHOS::DistributedData \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_event.h b/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_event.h similarity index 54% rename from datamgr_service/services/distributeddataservice/service/rdb/rdb_event.h rename to datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_event.h index d3d83c33..2ef233a7 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_event.h +++ b/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_event.h @@ -13,34 +13,27 @@ * limitations under the License. */ -#ifndef OHOS_DISTRIBUTED_DATA_SERVICES_RDB_RDB_EVENT_H -#define OHOS_DISTRIBUTED_DATA_SERVICES_RDB_RDB_EVENT_H +#ifndef OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_CLOUD_CLOUD_EVENT_H +#define OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_CLOUD_CLOUD_EVENT_H #include #include "eventcenter/event.h" -namespace OHOS::DistributedRdb { -class RdbEvent : public DistributedData::Event { +namespace OHOS::DistributedData { +class CloudEvent : public Event { public: enum : int32_t { - RDB_FEATURE_INIT = EVT_RDB, - RDB_CREATE, - RDB_BUTT + CLOUD_RDB_FEATURE_INIT = EVT_CLOUD, + CLOUD_BUTT }; - RdbEvent(int32_t evtId, int32_t user, const std::string &bundleName, const std::string &storeName); - ~RdbEvent() = default; + CloudEvent(int32_t evtId, int32_t user); + ~CloudEvent() = default; int32_t GetUser() const; - std::string GetBundleName() const; - std::string GetStoreName() const; bool Equals(const DistributedData::Event &event) const override; private: int32_t user_; - int32_t schemaVersion_; - std::string bundleName_; - std::string storeName_; - std::string cloudId_; }; -} // namespace OHOS::DistributedRdb -#endif // OHOS_DISTRIBUTED_DATA_SERVICES_RDB_RDB_EVENT_H +} // namespace OHOS::DistributedData +#endif // OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_CLOUD_CLOUD_EVENT_H diff --git a/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_info.h b/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_info.h index 89b09e86..db56c3bd 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_info.h +++ b/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_info.h @@ -21,8 +21,8 @@ class API_EXPORT CloudInfo final : public Serializable { public: struct API_EXPORT AppInfo final : public Serializable { static constexpr uint32_t CURRENT_VERSION = 0x04000001; - std::string bundleName; - std::string appId; + std::string bundleName = ""; + std::string appId = ""; uint64_t version = CURRENT_VERSION; bool cloudSwitch = false; @@ -41,6 +41,7 @@ public: bool IsValid() const; bool IsExist(const std::string &appId) const; void DelApp(const std::string &appId); + AppInfo &GetApp(const std::string &appId); static std::string GetPrefix(const std::initializer_list &field); bool Marshal(json &node) const override; @@ -51,6 +52,7 @@ private: static constexpr const char *SCHEMA_PREFIX = "CLOUD_SCHEMA"; static std::string GetKey(const std::string &prefix, const std::initializer_list &fields); + AppInfo appNil_ {}; }; } #endif // OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_CLOUD_CLOUD_INFO_H diff --git a/datamgr_service/services/distributeddataservice/framework/include/cloud/schema_meta.h b/datamgr_service/services/distributeddataservice/framework/include/cloud/schema_meta.h index 6d1939e6..248befa1 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/cloud/schema_meta.h +++ b/datamgr_service/services/distributeddataservice/framework/include/cloud/schema_meta.h @@ -36,7 +36,7 @@ public: }; struct API_EXPORT Database final : public Serializable { - std::string name; + std::string name = ""; std::vector
tables; bool Marshal(json &node) const override; @@ -47,6 +47,7 @@ public: bool Marshal(json &node) const override; bool Unmarshal(const json &node) override; + Database GetDataBase(const std::string &storeId); }; } // namespace OHOS::DistributedData #endif // OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_CLOUD_SCHEMA_META_H diff --git a/datamgr_service/services/distributeddataservice/framework/include/eventcenter/event.h b/datamgr_service/services/distributeddataservice/framework/include/eventcenter/event.h index 5ee3a433..27bf9df2 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/eventcenter/event.h +++ b/datamgr_service/services/distributeddataservice/framework/include/eventcenter/event.h @@ -28,7 +28,7 @@ public: EVT_INITED, EVT_UPDATE, EVT_CUSTOM = 0x1000, - EVT_RDB = 0x2000 + EVT_CLOUD = 0x2000 }; API_EXPORT Event(int32_t evtId); API_EXPORT Event(Event &&) noexcept = delete; diff --git a/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.cpp b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.cpp index 983ca503..a035ab95 100644 --- a/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.cpp +++ b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.cpp @@ -20,6 +20,7 @@ #include "account/account_delegate.h" #include "checker/checker_manager.h" #include "cloud_syncer.h" +#include "cloud/cloud_event.h" #include "cloud/cloud_server.h" #include "eventcenter/event_center.h" #include "feature/feature_system.h" @@ -27,7 +28,6 @@ #include "utils/anonymous.h" #include "log_print.h" #include "metadata/meta_data_manager.h" -#include "rdb_event.h" namespace OHOS::CloudData { using namespace DistributedData; @@ -47,20 +47,16 @@ CloudServiceImpl::Factory::~Factory() {} CloudServiceImpl::CloudServiceImpl() { - EventCenter::GetInstance().Subscribe(RdbEvent::RDB_FEATURE_INIT, [this](const Event &event) { - auto instance = CloudServer::GetInstance(); - if (instance == nullptr) { - ZLOGI("no cloud server"); - return; - } - auto &rdbEvent = static_cast(event); - auto cloudInfo = instance->GetServerInfo(rdbEvent.GetUser()); - if (!cloudInfo.IsValid()) { - ZLOGI("accountId empty"); + EventCenter::GetInstance().Subscribe(CloudEvent::CLOUD_RDB_FEATURE_INIT, [this](const Event &event) { + auto &rdbEvent = static_cast(event); + CloudInfo cloudInfo; + cloudInfo.user = rdbEvent.GetUser(); + if (GetServerInfo(cloudInfo) != SUCCESS) { + ZLOGE("failed, user:%{public}d", rdbEvent.GetUser()); return; } UpdateCloudInfo(cloudInfo); - UpdateSchema(cloudInfo); + AddSchema(cloudInfo); }); } @@ -68,18 +64,14 @@ int32_t CloudServiceImpl::EnableCloud(const std::string &id, const std::map lg(mutex_); CloudInfo cloudInfo; - if (GetCloudInfo(id, cloudInfo) != SUCCESS) { + cloudInfo.id = id; + if (GetCloudInfo(cloudInfo) != SUCCESS) { return INVALID_ARGUMENT; } cloudInfo.enableCloud = true; for (const auto &item : switches) { std::string appId = GetAppId(item.first); - for (auto &app : cloudInfo.apps) { - if (app.appId == appId) { - app.cloudSwitch = item.second; - break; - } - } + cloudInfo.GetApp(appId).cloudSwitch = item.second; } if (!MetaDataManager::GetInstance().SaveMeta(cloudInfo.GetKey(), cloudInfo, true)) { return ERROR; @@ -91,7 +83,8 @@ int32_t CloudServiceImpl::DisableCloud(const std::string &id) { std::lock_guard lg(mutex_); CloudInfo cloudInfo; - if (GetCloudInfo(id, cloudInfo) != SUCCESS) { + cloudInfo.id = id; + if (GetCloudInfo(cloudInfo) != SUCCESS) { return INVALID_ARGUMENT; } cloudInfo.enableCloud = false; @@ -105,22 +98,17 @@ int32_t CloudServiceImpl::ChangeAppSwitch(const std::string &id, const std::stri { std::lock_guard lg(mutex_); CloudInfo cloudInfo; - if (GetCloudInfo(id, cloudInfo) != SUCCESS) { + cloudInfo.id = id; + if (GetCloudInfo(cloudInfo) != SUCCESS) { return INVALID_ARGUMENT; } - bool exist = false; std::string appId = GetAppId(bundleName); - for (auto &app : cloudInfo.apps) { - if (app.appId == appId) { - app.cloudSwitch = appSwitch; - exist = true; - break; - } - } - if (!exist) { + auto &app = cloudInfo.GetApp(appId); + if (app.appId.empty()) { ZLOGE("bundleName:%{public}s", bundleName.c_str()); return INVALID_ARGUMENT; } + app.cloudSwitch = appSwitch; if (!MetaDataManager::GetInstance().SaveMeta(cloudInfo.GetKey(), cloudInfo, true)) { return ERROR; } @@ -137,10 +125,91 @@ int32_t CloudServiceImpl::NotifyDataChange(const std::string &id, const std::str return 0; } -int32_t CloudServiceImpl::GetCloudInfo(const std::string &id, CloudInfo &cloudInfo) +int32_t CloudServiceImpl::Config(const std::string &id, const StoreInfo &storeInfo, std::string &schema) { + if (!CheckAccess(storeInfo.bundleName)) { + ZLOGE("permission denied"); + return ERROR; + } + auto tokenId = IPCSkeleton::GetCallingTokenID(); + CloudInfo cloudInfo; + cloudInfo.id = id; + cloudInfo.user = AccountDelegate::GetInstance()->GetUserByToken(tokenId);; + if (ConfigCloudInfo(storeInfo, cloudInfo) != SUCCESS) { + return ERROR; + } + UpdateSchema(cloudInfo, storeInfo, storeInfo.version); + if (GetStoreSchema(cloudInfo, storeInfo, schema) != SUCCESS) { + return ERROR; + } + return SUCCESS; +} + +int32_t CloudServiceImpl::ConfigCloudInfo(const StoreInfo &storeInfo, CloudInfo &cloudInfo) +{ + if (GetCloudInfo(cloudInfo) != SUCCESS && GetServerInfo(cloudInfo) != SUCCESS) { + ZLOGE("id:%{public}s", Anonymous::Change(cloudInfo.id).c_str()); + return ERROR; + } + auto appId = GetAppId(storeInfo.bundleName); + if (!cloudInfo.IsExist(appId)) { + CloudInfo::AppInfo appInfo; + appInfo.bundleName = storeInfo.bundleName; + appInfo.appId = appId; + cloudInfo.apps.emplace_back(appInfo); + } + MetaDataManager::GetInstance().SaveMeta(cloudInfo.GetKey(), cloudInfo, true); + return SUCCESS; +} + +int32_t CloudServiceImpl::GetStoreSchema( + const CloudInfo &cloudInfo, const StoreInfo &storeInfo, std::string &schema) +{ + auto appId = GetAppId(storeInfo.bundleName); + if (!cloudInfo.IsExist(appId)) { + ZLOGE("no exist bundleName:%{public}s", storeInfo.bundleName.c_str()); + return ERROR; + } + SchemaMeta schemaMeta; + auto keys = cloudInfo.GetSchemaKey(); + if (!MetaDataManager::GetInstance().LoadMeta(keys[storeInfo.bundleName], schemaMeta, true)) { + ZLOGE("schema empty bundleName:%{public}s", storeInfo.bundleName.c_str()); + return ERROR; + } + auto database = schemaMeta.GetDataBase(storeInfo.storeId); + if (database.name.empty()) { + ZLOGE("storeId:%{public}s", storeInfo.storeId.c_str()); + return ERROR; + } + schema = Serializable::Marshall(database); + return SUCCESS; +} + +int32_t CloudServiceImpl::ClearConfig(const std::string &id, const StoreInfo &storeInfo) +{ + if (!CheckAccess(storeInfo.bundleName)) { + ZLOGE("permission denied"); + return ERROR; + } + + CloudInfo cloudInfo; cloudInfo.id = id; - uint32_t tokenId = IPCSkeleton::GetCallingTokenID(); + if (GetCloudInfo(cloudInfo) != SUCCESS) { + ZLOGE("id:%{public}s", Anonymous::Change(cloudInfo.id).c_str()); + return ERROR; + } + auto appId = GetAppId(storeInfo.bundleName); + if (cloudInfo.IsExist(appId)) { + auto keys = cloudInfo.GetSchemaKey(); + MetaDataManager::GetInstance().DelMeta(keys[storeInfo.bundleName], true); + cloudInfo.DelApp(appId); + } + return SUCCESS; +} + +int32_t CloudServiceImpl::GetCloudInfo(CloudInfo &cloudInfo) +{ + auto tokenId = IPCSkeleton::GetCallingTokenID(); cloudInfo.user = AccountDelegate::GetInstance()->GetUserByToken(tokenId); if (!MetaDataManager::GetInstance().LoadMeta(cloudInfo.GetKey(), cloudInfo, true)) { ZLOGE("invalid argument id:%{public}s, user:%{public}d", @@ -150,6 +219,19 @@ int32_t CloudServiceImpl::GetCloudInfo(const std::string &id, CloudInfo &cloudIn return SUCCESS; } +int32_t CloudServiceImpl::GetServerInfo(CloudInfo &cloudInfo) +{ + auto instance = CloudServer::GetInstance(); + if (instance == nullptr) { + return SERVER_UNAVAILABLE; + } + cloudInfo = instance->GetServerInfo(cloudInfo.user); + if (!cloudInfo.IsValid()) { + return ERROR; + } + return SUCCESS; +} + std::string CloudServiceImpl::GetAppId(const std::string &bundleName) { CheckerManager::StoreInfo storeInfo; @@ -159,7 +241,16 @@ std::string CloudServiceImpl::GetAppId(const std::string &bundleName) return CheckerManager::GetInstance().GetAppId(storeInfo); } -void CloudServiceImpl::UpdateCloudInfo(DistributedData::CloudInfo &cloudInfo) +bool CloudServiceImpl::CheckAccess(const std::string &bundleName) +{ + CheckerManager::StoreInfo storeInfo; + storeInfo.uid = IPCSkeleton::GetCallingUid(); + storeInfo.tokenId = IPCSkeleton::GetCallingTokenID(); + storeInfo.bundleName = bundleName; + return CheckerManager::GetInstance().IsValid(storeInfo); +} + +void CloudServiceImpl::UpdateCloudInfo(CloudInfo &cloudInfo) { CloudInfo oldInfo; if (!MetaDataManager::GetInstance().LoadMeta(cloudInfo.GetKey(), oldInfo, true)) { @@ -172,7 +263,7 @@ void CloudServiceImpl::UpdateCloudInfo(DistributedData::CloudInfo &cloudInfo) MetaDataManager::GetInstance().SaveMeta(oldInfo.GetKey(), oldInfo, true); } -void CloudServiceImpl::UpdateSchema(DistributedData::CloudInfo &cloudInfo) +void CloudServiceImpl::AddSchema(CloudInfo &cloudInfo) { auto keys = cloudInfo.GetSchemaKey(); for (const auto &key : keys) { @@ -180,13 +271,45 @@ void CloudServiceImpl::UpdateSchema(DistributedData::CloudInfo &cloudInfo) if (MetaDataManager::GetInstance().LoadMeta(key.second, schemaMeta, true)) { continue; } - auto instance = CloudServer::GetInstance(); - if (instance == nullptr) { - ZLOGE("no cloud server"); - return; + if (GetAppSchema(cloudInfo.user, key.first, schemaMeta) != SUCCESS) { + continue; } - schemaMeta = instance->GetAppSchema(cloudInfo.user, key.first); MetaDataManager::GetInstance().SaveMeta(key.second, schemaMeta, true); } } -} \ No newline at end of file + +int32_t CloudServiceImpl::GetAppSchema( + int32_t user, const std::string &bundleName, SchemaMeta &schemaMeta) +{ + auto instance = CloudServer::GetInstance(); + if (instance == nullptr) { + return SERVER_UNAVAILABLE; + } + schemaMeta = instance->GetAppSchema(user, bundleName); + return SUCCESS; +} + +void CloudServiceImpl::UpdateSchema(CloudInfo &cloudInfo, const StoreInfo &storeInfo, int32_t version) +{ + auto keys = cloudInfo.GetSchemaKey(); + SchemaMeta schemaMeta; + if (!MetaDataManager::GetInstance().LoadMeta(keys[storeInfo.bundleName], schemaMeta, true)) { + AddSchema(cloudInfo); + return; + } + if (version <= schemaMeta.version) { + ZLOGI("input ver:%{public}d, meta ver:%{public}d", version, schemaMeta.version); + return; + } + SchemaMeta serverMeta; + if (GetAppSchema(cloudInfo.user, storeInfo.bundleName, serverMeta) != SUCCESS) { + ZLOGI("get schema meta fail"); + return; + } + if (serverMeta.version != version) { + ZLOGI("input ver:%{public}d, server ver:%{public}d", version, serverMeta.version); + return; + } + MetaDataManager::GetInstance().SaveMeta(keys[storeInfo.bundleName], serverMeta, true); +} +} // OHOS::CloudData \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.h b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.h index d2dec093..afb98b0c 100644 --- a/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.h +++ b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.h @@ -19,6 +19,7 @@ #include #include "cloud_service_stub.h" #include "cloud/cloud_info.h" +#include "cloud/schema_meta.h" namespace OHOS::CloudData { class CloudServiceImpl : public CloudServiceStub { @@ -30,6 +31,9 @@ public: int32_t ChangeAppSwitch(const std::string &id, const std::string &bundleName, int32_t appSwitch) override; int32_t Clean(const std::string &id, const std::map &actions) override; int32_t NotifyDataChange(const std::string &id, const std::string &bundleName) override; + int32_t Config(const std::string &id, const StoreInfo &storeInfo, std::string &schema) override; + int32_t ClearConfig(const std::string &id, const StoreInfo &storeInfo) override; + private: class Factory { public: @@ -40,10 +44,19 @@ private: }; static Factory factory_; - void UpdateCloudInfo(DistributedData::CloudInfo &cloudInfo); - void UpdateSchema(DistributedData::CloudInfo &cloudInfo); - int32_t GetCloudInfo(const std::string &id, DistributedData::CloudInfo &cloudInfo); + using CloudInfo = DistributedData::CloudInfo; + using SchemaMeta = DistributedData::SchemaMeta; + + void UpdateCloudInfo(CloudInfo &cloudInfo); + void AddSchema(CloudInfo &cloudInfo); + void UpdateSchema(CloudInfo &cloudInfo, const StoreInfo &storeInfo, int32_t version); + int32_t ConfigCloudInfo(const StoreInfo &storeInfo, CloudInfo &cloudInfo); + int32_t GetStoreSchema(const CloudInfo &cloudInfo, const StoreInfo &storeInfo, std::string &schema); + int32_t GetCloudInfo(CloudInfo &cloudInfo); + int32_t GetServerInfo(CloudInfo &cloudInfo); + int32_t GetAppSchema(int32_t user, const std::string &bundleName, SchemaMeta &schemaMeta); std::string GetAppId(const std::string &bundleName); + bool CheckAccess(const std::string &bundleName); std::mutex mutex_; }; } // namespace OHOS::DistributedData diff --git a/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_stub.cpp b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_stub.cpp index 2ccf869e..ae472364 100644 --- a/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_stub.cpp +++ b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_stub.cpp @@ -27,6 +27,8 @@ const CloudServiceStub::Handler CloudServiceStub::HANDLERS[TRANS_BUTT] = { &CloudServiceStub::OnChangeAppSwitch, &CloudServiceStub::OnClean, &CloudServiceStub::OnNotifyDataChange, + &CloudServiceStub::OnConfig, + &CloudServiceStub::OnClearConfig, }; int CloudServiceStub::OnRemoteRequest(uint32_t code, OHOS::MessageParcel &data, OHOS::MessageParcel &reply) @@ -101,4 +103,27 @@ int32_t CloudServiceStub::OnNotifyDataChange(const std::string &id, MessageParce auto result = NotifyDataChange(id, bundleName); return ITypesUtil::Marshal(reply, result) ? ERR_NONE : IPC_STUB_WRITE_PARCEL_ERR; } + +int32_t CloudServiceStub::OnConfig(const std::string &id, MessageParcel &data, MessageParcel &reply) +{ + StoreInfo storeInfo; + if (!ITypesUtil::Unmarshal(data, storeInfo)) { + ZLOGE("Unmarshal id:%{public}s", Anonymous::Change(id).c_str()); + return IPC_STUB_INVALID_DATA_ERR; + } + std::string schema; + auto result = Config(id, storeInfo, schema); + return ITypesUtil::Marshal(reply, result, schema) ? ERR_NONE : IPC_STUB_WRITE_PARCEL_ERR; +} + +int32_t CloudServiceStub::OnClearConfig(const std::string &id, MessageParcel &data, MessageParcel &reply) +{ + StoreInfo storeInfo; + if (!ITypesUtil::Unmarshal(data, storeInfo)) { + ZLOGE("Unmarshal id:%{public}s", Anonymous::Change(id).c_str()); + return IPC_STUB_INVALID_DATA_ERR; + } + auto result = ClearConfig(id, storeInfo); + return ITypesUtil::Marshal(reply, result) ? ERR_NONE : IPC_STUB_WRITE_PARCEL_ERR; +} } // namespace OHOS::CloudData diff --git a/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_stub.h b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_stub.h index 4175015d..f1f3cd62 100644 --- a/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_stub.h +++ b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_stub.h @@ -31,6 +31,8 @@ private: int32_t OnChangeAppSwitch(const std::string &id, MessageParcel &data, MessageParcel &reply); int32_t OnClean(const std::string &id, MessageParcel &data, MessageParcel &reply); int32_t OnNotifyDataChange(const std::string &id, MessageParcel &data, MessageParcel &reply); + int32_t OnConfig(const std::string &id, MessageParcel &data, MessageParcel &reply); + int32_t OnClearConfig(const std::string &id, MessageParcel &data, MessageParcel &reply); static const Handler HANDLERS[TRANS_BUTT]; }; } // namespace OHOS::CloudData diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.cpp b/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.cpp index 35a9fbf1..a0a29d01 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.cpp +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.cpp @@ -17,7 +17,7 @@ #include "accesstoken_kit.h" #include "account/account_delegate.h" #include "checker/checker_manager.h" -#include "cloud/cloud_server.h" +#include "cloud/cloud_event.h" #include "communicator/device_manager_adapter.h" #include "crypto_manager.h" #include "eventcenter/event_center.h" @@ -26,7 +26,6 @@ #include "metadata/meta_data_manager.h" #include "metadata/store_meta_data.h" #include "permission/permission_validator.h" -#include "rdb_event.h" #include "rdb_notifier_proxy.h" #include "types_export.h" #include "utils/anonymous.h" @@ -390,100 +389,6 @@ int32_t RdbServiceImpl::RemoteQuery(const RdbSyncerParam& param, const std::stri return syncer->RemoteQuery(device, sql, selectionArgs, resultSet); } -int32_t RdbServiceImpl::CloudConfig(const CloudParam ¶m, std::string &schema) -{ - if (!CheckAccess({.bundleName_ = param.bundleName, .storeName_ = param.storeName})) { - ZLOGE("permission error"); - return RDB_ERROR; - } - auto tokenId = IPCSkeleton::GetCallingTokenID(); - auto user = AccountDelegate::GetInstance()->GetUserByToken(tokenId); - if (ConfigCloudInfo(param, user) != RDB_OK) { - return RDB_ERROR; - } - auto createEvt = std::make_unique( - RdbEvent::RDB_CREATE, user, param.bundleName, RdbSyncer::RemoveSuffix(param.storeName)); - EventCenter::GetInstance().PostEvent(std::move(createEvt)); - if (GetSchema(param, user, schema) != RDB_OK) { - return RDB_ERROR; - } - return RDB_OK; -} - -int32_t RdbServiceImpl::GetSchema(const CloudParam ¶m, int32_t user, std::string &schema) -{ - CloudInfo cloudInfo; - cloudInfo.id = param.cloudId; - cloudInfo.user = user; - if (!MetaDataManager::GetInstance().LoadMeta(cloudInfo.GetKey(), cloudInfo, true)) { - ZLOGE("cloudId:%{public}s, user:%{public}d", param.cloudId.c_str(), user); - return RDB_ERROR; - } - auto appId = GetAppId(param.bundleName); - if (!cloudInfo.IsExist(appId)) { - ZLOGE("bundleName:%{public}s", param.bundleName.c_str()); - return RDB_ERROR; - } - SchemaMeta schemaMeta; - auto keys = cloudInfo.GetSchemaKey(); - if (!MetaDataManager::GetInstance().LoadMeta(keys[param.bundleName], schemaMeta, true)) { - ZLOGE("schema empty, bundleName:%{public}s", param.bundleName.c_str()); - return RDB_ERROR; - } - schema = Serializable::Marshall(schemaMeta); - return RDB_OK; -} - -int32_t RdbServiceImpl::ConfigCloudInfo(const CloudParam ¶m, int32_t user) -{ - CloudInfo cloudInfo; - cloudInfo.id = param.cloudId; - cloudInfo.user = user; - if (!MetaDataManager::GetInstance().LoadMeta(cloudInfo.GetKey(), cloudInfo, true)) { - auto instance = CloudServer::GetInstance(); - if (instance == nullptr) { - return RDB_ERROR; - } - cloudInfo = instance->GetServerInfo(user); - if (!cloudInfo.IsValid()) { - return RDB_ERROR; - } - } - auto appId = GetAppId(param.bundleName); - if (!cloudInfo.IsExist(appId)) { - CloudInfo::AppInfo appInfo; - appInfo.bundleName = param.bundleName; - appInfo.appId = appId; - cloudInfo.apps.emplace_back(appInfo); - } - MetaDataManager::GetInstance().SaveMeta(cloudInfo.GetKey(), cloudInfo, true); - return RDB_OK; -} - -int32_t RdbServiceImpl::ClearCloudConfig(const CloudParam ¶m) -{ - if (!CheckAccess({.bundleName_ = param.bundleName, .storeName_ = param.storeName})) { - ZLOGE("permission error"); - return RDB_ERROR; - } - auto tokenId = IPCSkeleton::GetCallingTokenID(); - CloudInfo cloudInfo; - cloudInfo.user = AccountDelegate::GetInstance()->GetUserByToken(tokenId); - cloudInfo.id = param.cloudId; - if (!MetaDataManager::GetInstance().LoadMeta(cloudInfo.GetKey(), cloudInfo, true)) { - ZLOGE("invalid argument id:%{public}s, user:%{public}d", - Anonymous::Change(cloudInfo.id).c_str(), cloudInfo.user); - return RDB_ERROR; - } - auto appId = GetAppId(param.bundleName); - if (cloudInfo.IsExist(appId)) { - auto keys = cloudInfo.GetSchemaKey(); - MetaDataManager::GetInstance().DelMeta(keys[param.bundleName], true); - cloudInfo.DelApp(appId); - } - return RDB_OK; -} - std::string RdbServiceImpl::GetAppId(const std::string &bundleName) { CheckerManager::StoreInfo storeInfo; @@ -553,7 +458,7 @@ int32_t RdbServiceImpl::OnInitialize() { auto tokenId = IPCSkeleton::GetCallingTokenID(); auto user = AccountDelegate::GetInstance()->GetUserByToken(tokenId); - auto initEvt = std::make_unique(RdbEvent::RDB_FEATURE_INIT, user, "", ""); + auto initEvt = std::make_unique(CloudEvent::CLOUD_RDB_FEATURE_INIT, user); EventCenter::GetInstance().PostEvent(std::move(initEvt)); return RDB_OK; } diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.h b/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.h index 64792d8d..0961337a 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.h +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.h @@ -69,10 +69,6 @@ protected: int32_t DoUnSubscribe(const RdbSyncerParam& param) override; - int32_t CloudConfig(const CloudParam ¶m, std::string &schema) override; - - int32_t ClearCloudConfig(const CloudParam ¶m) override; - private: std::string GenIdentifier(const RdbSyncerParam& param); @@ -84,10 +80,6 @@ private: void OnAsyncComplete(pid_t pid, uint32_t seqNum, const SyncResult& result); - int32_t ConfigCloudInfo(const CloudParam ¶m, int32_t user); - - int32_t GetSchema(const CloudParam ¶m, int32_t user, std::string &schema); - std::string GetAppId(const std::string &bundleName); class DeathRecipientImpl : public IRemoteObject::DeathRecipient { diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_stub.cpp b/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_stub.cpp index de06ccf8..137a0598 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_stub.cpp +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_stub.cpp @@ -186,31 +186,4 @@ int32_t RdbServiceStub::OnRemoteDoDestroyTable(MessageParcel &data, MessageParce int32_t status = DestroyRDBTable(param); return ITypesUtil::Marshal(reply, status) ? RDB_OK : RDB_ERROR; } - -int32_t RdbServiceStub::OnRemoteDoCloudConfig(MessageParcel& data, MessageParcel& reply) -{ - CloudParam param; - if (!ITypesUtil::Unmarshal(data, param)) { - ZLOGE("read from message parcel failed"); - reply.WriteInt32(RDB_ERROR); - return RDB_OK; - } - - std::string schema; - int32_t status = CloudConfig(param, schema); - return ITypesUtil::Marshal(reply, status, schema) ? RDB_OK : RDB_ERROR; -} - -int32_t RdbServiceStub::OnRemoteDoClearCloudConfig(MessageParcel& data, MessageParcel& reply) -{ - CloudParam param; - if (!ITypesUtil::Unmarshal(data, param)) { - ZLOGE("read from message parcel failed"); - reply.WriteInt32(RDB_ERROR); - return RDB_OK; - } - - int32_t status = ClearCloudConfig(param); - return ITypesUtil::Marshal(reply, status) ? RDB_OK : RDB_ERROR; -} } // namespace OHOS::DistributedRdb diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_stub.h b/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_stub.h index 49599de2..901a7d6e 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_stub.h +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_stub.h @@ -68,10 +68,6 @@ private: int32_t OnRemoteDoDestroyTable(MessageParcel& data, MessageParcel& reply); - int32_t OnRemoteDoCloudConfig(MessageParcel& data, MessageParcel& reply); - - int32_t OnRemoteDoClearCloudConfig(MessageParcel& data, MessageParcel& reply); - using RequestHandle = int (RdbServiceStub::*)(MessageParcel &, MessageParcel &); static constexpr RequestHandle HANDLERS[RDB_SERVICE_CMD_MAX] = { [RDB_SERVICE_CMD_OBTAIN_TABLE] = &RdbServiceStub::OnRemoteObtainDistributedTableName, @@ -83,9 +79,7 @@ private: [RDB_SERVICE_CMD_UNSUBSCRIBE] = &RdbServiceStub::OnRemoteDoUnSubscribe, [RDB_SERVICE_CMD_REMOTE_QUERY] = &RdbServiceStub::OnRemoteDoRemoteQuery, [RDB_SERVICE_CREATE_RDB_TABLE] = &RdbServiceStub::OnRemoteDoCreateTable, - [RDB_SERVICE_DESTROY_RDB_TABLE] = &RdbServiceStub::OnRemoteDoDestroyTable, - [RDB_SERVICE_CLOUD_CONFIG] = &RdbServiceStub::OnRemoteDoCloudConfig, - [RDB_SERVICE_CLEAR_CLOUD_CONFIG] = &RdbServiceStub::OnRemoteDoClearCloudConfig + [RDB_SERVICE_DESTROY_RDB_TABLE] = &RdbServiceStub::OnRemoteDoDestroyTable }; }; } // namespace OHOS::DistributedRdb diff --git a/relational_store/frameworks/native/cloud_data/include/cloud_service_proxy.h b/relational_store/frameworks/native/cloud_data/include/cloud_service_proxy.h index 8ece3de8..a45f62a3 100644 --- a/relational_store/frameworks/native/cloud_data/include/cloud_service_proxy.h +++ b/relational_store/frameworks/native/cloud_data/include/cloud_service_proxy.h @@ -17,7 +17,7 @@ #define OHOS_DISTRIBUTED_DATA_CLOUD_CLOUD_SERVICE_PROXY_H #include "icloud_service.h" -#include "iremote_object.h"" +#include "iremote_object.h" #include "iremote_proxy.h" namespace OHOS::CloudData { @@ -30,6 +30,8 @@ public: int32_t ChangeAppSwitch(const std::string &id, const std::string &bundleName, int32_t appSwitch) override; int32_t Clean(const std::string &id, const std::map &actions) override; int32_t NotifyDataChange(const std::string &id, const std::string &bundleName) override; + int32_t Config(const std::string &id, const StoreInfo &storeInfo, std::string &schema) override; + int32_t ClearConfig(const std::string &id, const StoreInfo &storeInfo) override; private: sptr remote_; diff --git a/relational_store/frameworks/native/cloud_data/include/cloud_types_util.h b/relational_store/frameworks/native/cloud_data/include/cloud_types_util.h new file mode 100644 index 00000000..8dbd969d --- /dev/null +++ b/relational_store/frameworks/native/cloud_data/include/cloud_types_util.h @@ -0,0 +1,30 @@ +/* + * 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_DISTRIBUTED_DATA_CLOUD_CLOUD_TYPES_UTIL_H +#define OHOS_DISTRIBUTED_DATA_CLOUD_CLOUD_TYPES_UTIL_H + +#include "cloud_service.h" +#include "itypes_util.h" +#include "rdb_visibility.h" + +namespace OHOS::ITypesUtil { +using StoreInfo = CloudData::CloudService::StoreInfo; +template<> +RDB_API_EXPORT bool Marshalling(const StoreInfo &input, MessageParcel &data); +template<> +RDB_API_EXPORT bool Unmarshalling(StoreInfo &output, MessageParcel &data); +} // namespace OHOS::ITypesUtil +#endif // OHOS_DISTRIBUTED_DATA_CLOUD_CLOUD_TYPES_UTIL_H diff --git a/relational_store/frameworks/native/cloud_data/src/cloud_service_proxy.cpp b/relational_store/frameworks/native/cloud_data/src/cloud_service_proxy.cpp index fd295595..833cb5a3 100644 --- a/relational_store/frameworks/native/cloud_data/src/cloud_service_proxy.cpp +++ b/relational_store/frameworks/native/cloud_data/src/cloud_service_proxy.cpp @@ -102,4 +102,27 @@ int32_t CloudServiceProxy::NotifyDataChange(const std::string &id, const std::st } return static_cast(status); } + +int32_t CloudServiceProxy::Config(const std::string &id, const StoreInfo &storeInfo, std::string &schema) +{ + MessageParcel reply; + int32_t status = IPC_SEND(TRANS_CONFIG, reply, id, storeInfo); + if (status != SUCCESS) { + ZLOGE("status:0x%{public}x id:%{public}.6s bundleName:%{public}s, storeId:%{public}s", + status, id.c_str(), storeInfo.bundleName.c_str(), storeInfo.storeId.c_str()); + } + ITypesUtil::Unmarshal(reply, schema); + return static_cast(status); +} + +int32_t CloudServiceProxy::ClearConfig(const std::string &id, const StoreInfo &storeInfo) +{ + MessageParcel reply; + int32_t status = IPC_SEND(TRANS_CLEAR_CONFIG, reply, id, storeInfo); + if (status != SUCCESS) { + ZLOGE("status:0x%{public}x id:%{public}.6s bundleName:%{public}s, storeId:%{public}s", + status, id.c_str(), storeInfo.bundleName.c_str(), storeInfo.storeId.c_str()); + } + return static_cast(status); +} } // namespace OHOS::CloudData \ No newline at end of file diff --git a/relational_store/frameworks/native/cloud_data/src/cloud_types_util.cpp b/relational_store/frameworks/native/cloud_data/src/cloud_types_util.cpp new file mode 100644 index 00000000..d127971f --- /dev/null +++ b/relational_store/frameworks/native/cloud_data/src/cloud_types_util.cpp @@ -0,0 +1,30 @@ +/* + * 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. + */ + +#include "cloud_types_util.h" + +namespace OHOS::ITypesUtil { +template<> +bool Marshalling(const StoreInfo &input, MessageParcel &data) +{ + return ITypesUtil::Marshal(data, input.bundleName, input.storeId, input.version); +} +template<> +bool Unmarshalling(StoreInfo &output, MessageParcel &data) +{ + return ITypesUtil::Unmarshal(data, output.bundleName, output.storeId, output.version); +} +} // namespace OHOS::ITypesUtil + \ No newline at end of file diff --git a/relational_store/frameworks/native/rdb/include/rdb_service_proxy.h b/relational_store/frameworks/native/rdb/include/rdb_service_proxy.h index 333616f0..b7166e23 100644 --- a/relational_store/frameworks/native/rdb/include/rdb_service_proxy.h +++ b/relational_store/frameworks/native/rdb/include/rdb_service_proxy.h @@ -67,10 +67,6 @@ protected: int32_t DoUnSubscribe(const RdbSyncerParam& param) override; - int32_t CloudConfig(const CloudParam& param, std::string &schema) override; - - int32_t ClearCloudConfig(const CloudParam& param) override; - private: uint32_t GetSeqNum(); diff --git a/relational_store/frameworks/native/rdb/include/rdb_types_util.h b/relational_store/frameworks/native/rdb/include/rdb_types_util.h index ca589d37..71dcf135 100644 --- a/relational_store/frameworks/native/rdb/include/rdb_types_util.h +++ b/relational_store/frameworks/native/rdb/include/rdb_types_util.h @@ -21,7 +21,6 @@ #include "values_bucket.h" #include "rdb_visibility.h" namespace OHOS::ITypesUtil { -using CloudParam = DistributedRdb::CloudParam; using SyncerParam = DistributedRdb::RdbSyncerParam; using SyncOption = DistributedRdb::SyncOption; using RdbPredicates = DistributedRdb::RdbPredicates; @@ -57,9 +56,5 @@ template<> bool Marshalling(const Asset &input, MessageParcel &data); template<> bool Unmarshalling(Asset &output, MessageParcel &data); -template<> -bool Marshalling(const CloudParam &input, MessageParcel &data); -template<> -bool Unmarshalling(CloudParam &output, MessageParcel &data); } #endif // DISTRIBUTED_RDB_RDB_TYPES_UTIL_H diff --git a/relational_store/frameworks/native/rdb/src/rdb_service_proxy.cpp b/relational_store/frameworks/native/rdb/src/rdb_service_proxy.cpp index a8f00b9d..760709ad 100644 --- a/relational_store/frameworks/native/rdb/src/rdb_service_proxy.cpp +++ b/relational_store/frameworks/native/rdb/src/rdb_service_proxy.cpp @@ -282,30 +282,6 @@ int32_t RdbServiceProxy::DoUnSubscribe(const RdbSyncerParam ¶m) return status; } -int32_t RdbServiceProxy::CloudConfig(const CloudParam ¶m, std::string &schema) -{ - MessageParcel reply; - int32_t status = IPC_SEND(RDB_SERVICE_CLOUD_CONFIG, reply, param); - if (status != RDB_OK) { - ZLOGE("status:%{public}d, bundleName:%{public}s, storeName:%{public}s, cloudId:%{public}.6s", - status, param.bundleName.c_str(), param.storeName.c_str(), param.cloudId.c_str()); - return status; - } - ITypesUtil::Unmarshal(reply, schema); - return RDB_OK; -} - -int32_t RdbServiceProxy::ClearCloudConfig(const CloudParam ¶m) -{ - MessageParcel reply; - int32_t status = IPC_SEND(RDB_SERVICE_CLEAR_CLOUD_CONFIG, reply, param); - if (status != RDB_OK) { - ZLOGE("status:%{public}d, bundleName:%{public}s, storeName:%{public}s, cloudId:%{public}.6s", - status, param.bundleName.c_str(), param.storeName.c_str(), param.cloudId.c_str()); - } - return status; -} - int32_t RdbServiceProxy::RemoteQuery(const RdbSyncerParam& param, const std::string& device, const std::string& sql, const std::vector& selectionArgs, sptr& resultSet) { diff --git a/relational_store/frameworks/native/rdb/src/rdb_types_util.cpp b/relational_store/frameworks/native/rdb/src/rdb_types_util.cpp index d7ed7c9e..a45c56c2 100644 --- a/relational_store/frameworks/native/rdb/src/rdb_types_util.cpp +++ b/relational_store/frameworks/native/rdb/src/rdb_types_util.cpp @@ -98,14 +98,4 @@ bool ITypesUtil::Unmarshalling(Asset &output, MessageParcel &data) { return ITypesUtil::Unmarshal(data, output.version, output.name, output.size, output.modifyTime, output.uri); } -template<> -bool Marshalling(const CloudParam &input, MessageParcel &data) -{ - return ITypesUtil::Marshal(data, input.bundleName, input.storeName, input.cloudId, input.schemaVerion); -} -template<> -bool Unmarshalling(CloudParam &output, MessageParcel &data) -{ - return ITypesUtil::Unmarshal(data, output.bundleName, output.storeName, output.cloudId, output.schemaVerion); } -} \ No newline at end of file diff --git a/relational_store/interfaces/inner_api/cloud_data/include/cloud_service.h b/relational_store/interfaces/inner_api/cloud_data/include/cloud_service.h index c7016761..e1645330 100644 --- a/relational_store/interfaces/inner_api/cloud_data/include/cloud_service.h +++ b/relational_store/interfaces/inner_api/cloud_data/include/cloud_service.h @@ -29,6 +29,8 @@ public: TRANS_CHANGE_APP_SWITCH, TRANS_CLEAN, TRANS_NOTIFY_DATA_CHANGE, + TRANS_CONFIG, + TRANS_CLEAR_CONFIG, TRANS_BUTT, }; enum Action : int32_t @@ -49,10 +51,17 @@ public: SUCCESS = 0, ERROR, INVALID_ARGUMENT, + SERVER_UNAVAILABLE, IPC_ERROR, IPC_PARCEL_ERROR }; + struct StoreInfo { + std::string bundleName; + std::string storeId; + int32_t version; + }; + static constexpr const char *SERVICE_NAME = "cloud"; virtual ~CloudService() = default; virtual int32_t EnableCloud(const std::string &id, const std::map &switches) = 0; @@ -60,6 +69,8 @@ public: virtual int32_t ChangeAppSwitch(const std::string &id, const std::string &bundleName, int32_t appSwitch) = 0; virtual int32_t Clean(const std::string &id, const std::map &actions) = 0; virtual int32_t NotifyDataChange(const std::string &id, const std::string &bundleName) = 0; + virtual int32_t Config(const std::string &id, const StoreInfo &storeInfo, std::string &schema) = 0; + virtual int32_t ClearConfig(const std::string &id, const StoreInfo &storeInfo) = 0; }; } // namespace OHOS::CloudData #endif // OHOS_DISTRIBUTED_DATA_CLOUD_CLOUD_SERVICE_H diff --git a/relational_store/interfaces/inner_api/rdb/include/rdb_service.h b/relational_store/interfaces/inner_api/rdb/include/rdb_service.h index bffb1ac3..a72ebf72 100644 --- a/relational_store/interfaces/inner_api/rdb/include/rdb_service.h +++ b/relational_store/interfaces/inner_api/rdb/include/rdb_service.h @@ -37,8 +37,6 @@ public: RDB_SERVICE_CMD_REMOTE_QUERY, RDB_SERVICE_CREATE_RDB_TABLE, RDB_SERVICE_DESTROY_RDB_TABLE, - RDB_SERVICE_CLOUD_CONFIG, - RDB_SERVICE_CLEAR_CLOUD_CONFIG, RDB_SERVICE_CMD_MAX }; virtual std::string ObtainDistributedTableName(const std::string &device, const std::string &table) = 0; @@ -73,10 +71,6 @@ protected: virtual int32_t DoSubscribe(const RdbSyncerParam ¶m) = 0; virtual int32_t DoUnSubscribe(const RdbSyncerParam ¶m) = 0; - - virtual int32_t CloudConfig(const CloudParam ¶m, std::string &schema) = 0; - - virtual int32_t ClearCloudConfig(const CloudParam ¶m) = 0; }; } } // namespace OHOS::DistributedRdb -- Gitee From ef6c104376b7a03311e855209a9951c427e3d362 Mon Sep 17 00:00:00 2001 From: zuojiangjiang Date: Sat, 15 Apr 2023 03:44:35 +0000 Subject: [PATCH 15/44] !22 update Merge pull request !22 from zuojiangjiang/cloud_dev --- .../framework/cloud/cloud_info.cpp | 12 +++--- .../framework/include/cloud/cloud_info.h | 6 +-- .../service/cloud/cloud_service_impl.cpp | 43 +++++++++++-------- .../test/native/cloud_data/BUILD.gn | 13 ++++++ 4 files changed, 48 insertions(+), 26 deletions(-) create mode 100644 relational_store/test/native/cloud_data/BUILD.gn diff --git a/datamgr_service/services/distributeddataservice/framework/cloud/cloud_info.cpp b/datamgr_service/services/distributeddataservice/framework/cloud/cloud_info.cpp index c0b0ccc8..4d022a2f 100644 --- a/datamgr_service/services/distributeddataservice/framework/cloud/cloud_info.cpp +++ b/datamgr_service/services/distributeddataservice/framework/cloud/cloud_info.cpp @@ -77,20 +77,20 @@ bool CloudInfo::IsValid() const return !id.empty(); } -bool CloudInfo::IsExist(const std::string &appId) const +bool CloudInfo::IsExist(const std::string &bundleName) const { for (const auto &app : apps) { - if (app.appId == appId) { + if (app.bundleName == bundleName) { return true; } } return false; } -void CloudInfo::DelApp(const std::string &appId) +void CloudInfo::DelApp(const std::string &bundleName) { for (auto it = apps.begin(); it != apps.end();) { - if ((*it).appId == appId) { + if ((*it).bundleName == bundleName) { it = apps.erase(it); break; } @@ -98,10 +98,10 @@ void CloudInfo::DelApp(const std::string &appId) } } -CloudInfo::AppInfo &CloudInfo::GetApp(const std::string &appId) +CloudInfo::AppInfo &CloudInfo::GetApp(const std::string &bundleName) { for (auto &app : apps) { - if (app.appId == appId) { + if (app.bundleName == bundleName) { return app; } } diff --git a/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_info.h b/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_info.h index db56c3bd..31339b79 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_info.h +++ b/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_info.h @@ -39,9 +39,9 @@ public: std::string GetKey() const; std::map GetSchemaKey() const; bool IsValid() const; - bool IsExist(const std::string &appId) const; - void DelApp(const std::string &appId); - AppInfo &GetApp(const std::string &appId); + bool IsExist(const std::string &bundleName) const; + void DelApp(const std::string &bundleName); + AppInfo &GetApp(const std::string &bundleName); static std::string GetPrefix(const std::initializer_list &field); bool Marshal(json &node) const override; diff --git a/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.cpp b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.cpp index a035ab95..8de4f2cf 100644 --- a/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.cpp +++ b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.cpp @@ -31,8 +31,6 @@ namespace OHOS::CloudData { using namespace DistributedData; -using namespace DistributedKv; -using namespace DistributedRdb; __attribute__((used)) CloudServiceImpl::Factory CloudServiceImpl::factory_; CloudServiceImpl::Factory::Factory() { FeatureSystem::GetInstance().RegisterCreator(CloudServiceImpl::SERVICE_NAME, [this]() { @@ -70,8 +68,7 @@ int32_t CloudServiceImpl::EnableCloud(const std::string &id, const std::map &actions) { - return 0; + CloudInfo cloudInfo; + cloudInfo.id = id; + if (GetCloudInfo(cloudInfo) != SUCCESS) { + ZLOGE("id:%{public}s", Anonymous::Change(id).c_str()); + return INVALID_ARGUMENT; + } + auto keys = cloudInfo.GetSchemaKey(); + for (const auto &action : actions) { + if (!cloudInfo.IsExist(action.first)) { + continue; + } + SchemaMeta schemaMeta; + if (MetaDataManager::GetInstance().LoadMeta(keys[action.first], schemaMeta, true)) { + // do action + } + } + return SUCCESS; } int32_t CloudServiceImpl::NotifyDataChange(const std::string &id, const std::string &bundleName) @@ -134,7 +146,7 @@ int32_t CloudServiceImpl::Config(const std::string &id, const StoreInfo &storeIn auto tokenId = IPCSkeleton::GetCallingTokenID(); CloudInfo cloudInfo; cloudInfo.id = id; - cloudInfo.user = AccountDelegate::GetInstance()->GetUserByToken(tokenId);; + cloudInfo.user = DistributedKv::AccountDelegate::GetInstance()->GetUserByToken(tokenId);; if (ConfigCloudInfo(storeInfo, cloudInfo) != SUCCESS) { return ERROR; } @@ -151,11 +163,10 @@ int32_t CloudServiceImpl::ConfigCloudInfo(const StoreInfo &storeInfo, CloudInfo ZLOGE("id:%{public}s", Anonymous::Change(cloudInfo.id).c_str()); return ERROR; } - auto appId = GetAppId(storeInfo.bundleName); - if (!cloudInfo.IsExist(appId)) { + if (!cloudInfo.IsExist(storeInfo.bundleName)) { CloudInfo::AppInfo appInfo; appInfo.bundleName = storeInfo.bundleName; - appInfo.appId = appId; + appInfo.appId = GetAppId(storeInfo.bundleName); cloudInfo.apps.emplace_back(appInfo); } MetaDataManager::GetInstance().SaveMeta(cloudInfo.GetKey(), cloudInfo, true); @@ -165,8 +176,7 @@ int32_t CloudServiceImpl::ConfigCloudInfo(const StoreInfo &storeInfo, CloudInfo int32_t CloudServiceImpl::GetStoreSchema( const CloudInfo &cloudInfo, const StoreInfo &storeInfo, std::string &schema) { - auto appId = GetAppId(storeInfo.bundleName); - if (!cloudInfo.IsExist(appId)) { + if (!cloudInfo.IsExist(storeInfo.bundleName)) { ZLOGE("no exist bundleName:%{public}s", storeInfo.bundleName.c_str()); return ERROR; } @@ -198,11 +208,10 @@ int32_t CloudServiceImpl::ClearConfig(const std::string &id, const StoreInfo &st ZLOGE("id:%{public}s", Anonymous::Change(cloudInfo.id).c_str()); return ERROR; } - auto appId = GetAppId(storeInfo.bundleName); - if (cloudInfo.IsExist(appId)) { + if (cloudInfo.IsExist(storeInfo.bundleName)) { auto keys = cloudInfo.GetSchemaKey(); MetaDataManager::GetInstance().DelMeta(keys[storeInfo.bundleName], true); - cloudInfo.DelApp(appId); + cloudInfo.DelApp(storeInfo.bundleName); } return SUCCESS; } @@ -210,7 +219,7 @@ int32_t CloudServiceImpl::ClearConfig(const std::string &id, const StoreInfo &st int32_t CloudServiceImpl::GetCloudInfo(CloudInfo &cloudInfo) { auto tokenId = IPCSkeleton::GetCallingTokenID(); - cloudInfo.user = AccountDelegate::GetInstance()->GetUserByToken(tokenId); + cloudInfo.user = DistributedKv::AccountDelegate::GetInstance()->GetUserByToken(tokenId); if (!MetaDataManager::GetInstance().LoadMeta(cloudInfo.GetKey(), cloudInfo, true)) { ZLOGE("invalid argument id:%{public}s, user:%{public}d", Anonymous::Change(cloudInfo.id).c_str(), cloudInfo.user); diff --git a/relational_store/test/native/cloud_data/BUILD.gn b/relational_store/test/native/cloud_data/BUILD.gn new file mode 100644 index 00000000..021323f2 --- /dev/null +++ b/relational_store/test/native/cloud_data/BUILD.gn @@ -0,0 +1,13 @@ +# 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. + -- Gitee From 4dad410dece90db963449600060f0efec5a4e3da Mon Sep 17 00:00:00 2001 From: Sven Wang Date: Wed, 19 Apr 2023 10:22:56 +0800 Subject: [PATCH 16/44] update Signed-off-by: Sven Wang --- .../framework/cloud/schema_meta.cpp | 6 + .../framework/include/cloud/asset_loader.h | 6 +- .../framework/include/cloud/cloud_db.h | 8 ++ .../framework/include/cloud/cloud_info.h | 3 +- .../framework/include/cloud/cloud_server.h | 6 +- .../framework/include/cloud/schema_meta.h | 5 +- .../framework/include/store/general_store.h | 9 +- .../cloud_data/include/cloud_manager_impl.h | 51 -------- .../cloud_data/include/cloud_service_proxy.h | 1 - .../native/cloud_data/src/cloud_manager.cpp | 115 ++++++++++++++++- .../cloud_data/src/cloud_manager_impl.cpp | 122 ------------------ .../cloud_data/include/cloud_manager.h | 26 ++-- 12 files changed, 159 insertions(+), 199 deletions(-) delete mode 100644 relational_store/frameworks/native/cloud_data/include/cloud_manager_impl.h delete mode 100644 relational_store/frameworks/native/cloud_data/src/cloud_manager_impl.cpp diff --git a/datamgr_service/services/distributeddataservice/framework/cloud/schema_meta.cpp b/datamgr_service/services/distributeddataservice/framework/cloud/schema_meta.cpp index e8787106..b6a8cd4b 100644 --- a/datamgr_service/services/distributeddataservice/framework/cloud/schema_meta.cpp +++ b/datamgr_service/services/distributeddataservice/framework/cloud/schema_meta.cpp @@ -32,6 +32,7 @@ bool SchemaMeta::Unmarshal(const Serializable::json &node) bool SchemaMeta::Database::Marshal(Serializable::json &node) const { SetValue(node[GET_NAME(name)], name); + SetValue(node[GET_NAME(alias)], alias); SetValue(node[GET_NAME(tables)], tables); return true; } @@ -39,6 +40,7 @@ bool SchemaMeta::Database::Marshal(Serializable::json &node) const bool SchemaMeta::Database::Unmarshal(const Serializable::json &node) { GetValue(node, GET_NAME(name), name); + GetValue(node, GET_NAME(alias), alias); GetValue(node, GET_NAME(tables), tables); return true; } @@ -46,6 +48,7 @@ bool SchemaMeta::Database::Unmarshal(const Serializable::json &node) bool SchemaMeta::Table::Marshal(Serializable::json &node) const { SetValue(node[GET_NAME(name)], name); + SetValue(node[GET_NAME(alias)], alias); SetValue(node[GET_NAME(fields)], fields); return true; } @@ -53,6 +56,7 @@ bool SchemaMeta::Table::Marshal(Serializable::json &node) const bool SchemaMeta::Table::Unmarshal(const Serializable::json &node) { GetValue(node, GET_NAME(name), name); + GetValue(node, GET_NAME(alias), alias); GetValue(node, GET_NAME(fields), fields); return true; } @@ -60,6 +64,7 @@ bool SchemaMeta::Table::Unmarshal(const Serializable::json &node) bool SchemaMeta::Field::Marshal(Serializable::json &node) const { SetValue(node[GET_NAME(colName)], colName); + SetValue(node[GET_NAME(alias)], alias); SetValue(node[GET_NAME(type)], type); SetValue(node[GET_NAME(primary)], primary); SetValue(node[GET_NAME(nullable)], nullable); @@ -69,6 +74,7 @@ bool SchemaMeta::Field::Marshal(Serializable::json &node) const bool SchemaMeta::Field::Unmarshal(const Serializable::json &node) { GetValue(node, GET_NAME(colName), colName); + GetValue(node, GET_NAME(alias), alias); GetValue(node, GET_NAME(type), type); GetValue(node, GET_NAME(primary), primary); GetValue(node, GET_NAME(nullable), nullable); diff --git a/datamgr_service/services/distributeddataservice/framework/include/cloud/asset_loader.h b/datamgr_service/services/distributeddataservice/framework/include/cloud/asset_loader.h index eb8b227c..c4e9a797 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/cloud/asset_loader.h +++ b/datamgr_service/services/distributeddataservice/framework/include/cloud/asset_loader.h @@ -12,16 +12,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - #ifndef OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_CLOUD_ASSET_LOADER_H #define OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_CLOUD_ASSET_LOADER_H +#include #include "store/asset.h" namespace OHOS::DistributedData { class AssetLoader { public: virtual ~AssetLoader() = 0; - virtual int32_t Upload(const Asset &asset) = 0; - virtual int32_t Download(Asset &asset) = 0; + virtual int32_t Upload(const std::vector &asset) = 0; + virtual int32_t Download(std::vector &asset) = 0; }; } // namespace OHOS::DistributedData #endif // OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_CLOUD_ASSET_LOADER_H diff --git a/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_db.h b/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_db.h index fddab369..586abb1e 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_db.h +++ b/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_db.h @@ -19,6 +19,14 @@ namespace OHOS::DistributedData { class CloudDB : public GeneralStore { public: + virtual int32_t Execute(const std::string &table, const std::string &sql, const VBucket &extend) = 0; + virtual int32_t Insert(const std::string &table, VBucket &&values, VBucket &extend) = 0; + virtual int32_t BatchInsert(const std::string &table, VBuckets &&values, VBuckets &extends) = 0; + virtual int32_t Update(const std::string &table, VBucket &&values, const VBucket &extend) = 0; + virtual int32_t BatchUpdate(const std::string &table, VBuckets &&values, const VBuckets &extends) = 0; + virtual int32_t Delete(const std::string &table, const VBucket &extend) = 0; + virtual int32_t BatchDelete(const std::string &table, const VBuckets &extends) = 0; + virtual std::shared_ptr Query(const std::string &table, const VBuckets &extends) = 0; virtual int32_t Lock() = 0; virtual int32_t Unlock() = 0; virtual int32_t Flush() = 0; diff --git a/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_info.h b/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_info.h index 31339b79..baddad95 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_info.h +++ b/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_info.h @@ -20,10 +20,9 @@ namespace OHOS::DistributedData { class API_EXPORT CloudInfo final : public Serializable { public: struct API_EXPORT AppInfo final : public Serializable { - static constexpr uint32_t CURRENT_VERSION = 0x04000001; std::string bundleName = ""; std::string appId = ""; - uint64_t version = CURRENT_VERSION; + uint64_t version = 0; bool cloudSwitch = false; bool Marshal(json &node) const override; diff --git a/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_server.h b/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_server.h index f9c373c5..7fc0a9f1 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_server.h +++ b/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_server.h @@ -23,13 +23,13 @@ namespace OHOS::DistributedData { class CloudServer { public: + using Database = SchemaMeta::Database; API_EXPORT static CloudServer *GetInstance(); API_EXPORT static bool RegisterCloudInstance(CloudServer *instance); virtual CloudInfo GetServerInfo(int32_t userId) = 0; virtual SchemaMeta GetAppSchema(int32_t userId, const std::string &bundleName) = 0; - virtual std::shared_ptr ConnectAssetLoader(uint32_t tokenId, const std::string &cloudId) = 0; - virtual std::shared_ptr ConnectCloudDB(uint32_t tokenId, const std::string &cloudId, - const std::string &dbName) = 0; + virtual std::shared_ptr ConnectAssetLoader(uint32_t tokenId, const Database &dbMeta) = 0; + virtual std::shared_ptr ConnectCloudDB(uint32_t tokenId, const Database &dbMeta) = 0; private: static CloudServer *instance_; diff --git a/datamgr_service/services/distributeddataservice/framework/include/cloud/schema_meta.h b/datamgr_service/services/distributeddataservice/framework/include/cloud/schema_meta.h index 248befa1..4ae4a169 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/cloud/schema_meta.h +++ b/datamgr_service/services/distributeddataservice/framework/include/cloud/schema_meta.h @@ -21,7 +21,8 @@ class API_EXPORT SchemaMeta final : public Serializable { public: struct API_EXPORT Field final : public Serializable { std::string colName; - std::string type; + std::string alias; + int32_t type = 0; bool primary = false; bool nullable = true; bool Marshal(json &node) const override; @@ -30,6 +31,7 @@ public: struct API_EXPORT Table final : public Serializable { std::string name; + std::string alias; std::vector fields; bool Marshal(json &node) const override; bool Unmarshal(const json &node) override; @@ -37,6 +39,7 @@ public: struct API_EXPORT Database final : public Serializable { std::string name = ""; + std::string alias; std::vector
tables; bool Marshal(json &node) const override; diff --git a/datamgr_service/services/distributeddataservice/framework/include/store/general_store.h b/datamgr_service/services/distributeddataservice/framework/include/store/general_store.h index 8f5c93f4..2629480d 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/store/general_store.h +++ b/datamgr_service/services/distributeddataservice/framework/include/store/general_store.h @@ -28,6 +28,7 @@ public: E_ERROR, E_BUSY, E_INVALID_ARGS, + E_NOT_SUPPORT, E_BUTT, }; using Assets = std::vector; @@ -35,15 +36,19 @@ public: using Value = std::variant; using Values = std::vector; using VBucket = std::map; + using VBuckets = std::vector; + using Watcher = GeneralWatcher; virtual ~GeneralStore() = default; virtual int32_t Close() = 0; virtual int32_t Execute(const std::string &table, const std::string &sql) = 0; virtual int32_t Insert(const std::string &table, VBucket &&values) = 0; + virtual int32_t BatchInsert(const std::string &table, VBuckets &&values) = 0; virtual int32_t Update(const std::string &table, const std::string &sql, VBucket &&values) = 0; + virtual int32_t BatchUpdate(const std::string &table, const std::string &sql, VBuckets &&values) = 0; virtual int32_t Delete(const std::string &table, const std::string &sql, Values &&args) = 0; virtual std::shared_ptr Query(const std::string &table, const std::string &sql, Values &&args) = 0; - virtual int32_t Watch(int32_t origin, GeneralWatcher &watcher) = 0; - virtual int32_t Unwatch(int32_t origin, GeneralWatcher &watcher) = 0; + virtual int32_t Watch(int32_t origin, Watcher &watcher) = 0; + virtual int32_t Unwatch(int32_t origin, Watcher &watcher) = 0; }; } // namespace OHOS::DistributedData #endif // OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_STORE_GENERAL_STORE_H diff --git a/relational_store/frameworks/native/cloud_data/include/cloud_manager_impl.h b/relational_store/frameworks/native/cloud_data/include/cloud_manager_impl.h deleted file mode 100644 index 2c8501ee..00000000 --- a/relational_store/frameworks/native/cloud_data/include/cloud_manager_impl.h +++ /dev/null @@ -1,51 +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_DISTRIBUTED_DATA_CLOUD_CLOUD_MANAGER_IMPL_H -#define OHOS_DISTRIBUTED_DATA_CLOUD_CLOUD_MANAGER_IMPL_H - -#include -#include "cloud_service.h" -#include "cloud_service_proxy.h" -#include "icloud_service.h" -#include "iremote_object.h" -#include "iremote_proxy.h" - -namespace OHOS::CloudData { -class CloudDataServiceProxy; -class CloudManagerImpl { -public: - static CloudManagerImpl &GetInstance(); - std::shared_ptr GetCloudService(); - -private: - CloudManagerImpl() = default; - ~CloudManagerImpl() = default; - static std::shared_ptr GetDistributedDataManager(); - sptr GetCloudServiceProxy(); - - std::shared_ptr distributedDataMgr_; - std::mutex mutex_; - std::shared_ptr cloudService_; -}; - -class CloudDataServiceProxy : public IRemoteProxy { -public: - explicit CloudDataServiceProxy(const sptr &impl); - ~CloudDataServiceProxy() = default; - sptr GetFeatureInterface(const std::string &name) override; -}; -} // namespace OHOS::CloudData -#endif // OHOS_DISTRIBUTED_DATA_CLOUD_CLOUD_MANAGER_IMPL_H diff --git a/relational_store/frameworks/native/cloud_data/include/cloud_service_proxy.h b/relational_store/frameworks/native/cloud_data/include/cloud_service_proxy.h index a45f62a3..0c6e7844 100644 --- a/relational_store/frameworks/native/cloud_data/include/cloud_service_proxy.h +++ b/relational_store/frameworks/native/cloud_data/include/cloud_service_proxy.h @@ -35,7 +35,6 @@ public: private: sptr remote_; - static inline BrokerDelegator delegator_; }; } // namespace OHOS::CloudData #endif // OHOS_DISTRIBUTED_DATA_CLOUD_CLOUD_SERVICE_PROXY_H diff --git a/relational_store/frameworks/native/cloud_data/src/cloud_manager.cpp b/relational_store/frameworks/native/cloud_data/src/cloud_manager.cpp index c9a921c9..78823f7f 100644 --- a/relational_store/frameworks/native/cloud_data/src/cloud_manager.cpp +++ b/relational_store/frameworks/native/cloud_data/src/cloud_manager.cpp @@ -13,12 +13,123 @@ * limitations under the License. */ +#define LOG_TAG "CloudManagerImpl" + #include "cloud_manager.h" -#include "cloud_manager_impl.h" +#include "cloud_service_proxy.h" +#include "icloud_service.h" +#include "iservice_registry.h" +#include "itypes_util.h" +#include "log_print.h" +#include "system_ability_definition.h" namespace OHOS::CloudData { +class DataMgrService : public IRemoteProxy { +public: + explicit DataMgrService(const sptr &impl); + ~DataMgrService() = default; + sptr GetFeatureInterface(const std::string &name) override; +}; + +class CloudDeath : public IRemoteObject::DeathRecipient { +public: + CloudDeath(std::function action) : action_(std::move(action)){}; + void OnRemoteDied(const wptr &object) override + { + if (action_) { + action_(); + } + } + +private: + std::function action_; +}; + +CloudManager &CloudManager::GetInstance() +{ + static CloudManager instance; + return instance; +} + std::shared_ptr CloudManager::GetCloudService() { - return CloudManagerImpl::GetInstance().GetCloudService(); + std::lock_guard lg(mutex_); + if (cloudService_ != nullptr) { + return cloudService_; + } + + auto saMgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + if (saMgr == nullptr) { + ZLOGE("get system ability manager failed"); + return nullptr; + } + auto dataMgrObject = saMgr->CheckSystemAbility(DISTRIBUTED_KV_DATA_SERVICE_ABILITY_ID); + if (dataMgrObject == nullptr) { + ZLOGE("get distributed data manager failed"); + return nullptr; + } + + sptr dataMgr = new (std::nothrow) DataMgrService(dataMgrObject); + if (dataMgr == nullptr) { + ZLOGE("new CloudDataServiceProxy failed"); + return nullptr; + } + + auto cloudObject = dataMgr->GetFeatureInterface(CloudService::SERVICE_NAME); + if (cloudObject == nullptr) { + ZLOGE("get cloud service failed"); + return nullptr; + } + + cloudObject->AddDeathRecipient(new CloudDeath([this]() { + std::lock_guard lg(mutex_); + cloudService_ = nullptr; + })); + + sptr proxy = new (std::nothrow) CloudServiceProxy(cloudObject); + if (proxy == nullptr) { + return nullptr; + } + + cloudService_ = std::shared_ptr(proxy.GetRefPtr(), [holder = proxy](const auto *) {}); + if (cloudService_ == nullptr) { + return nullptr; + } + return cloudService_; +} + +DataMgrService::DataMgrService(const sptr &impl) : IRemoteProxy(impl) +{ + ZLOGI("init proxy"); +} + +sptr DataMgrService::GetFeatureInterface(const std::string &name) +{ + ZLOGI("%s", name.c_str()); + MessageParcel data; + if (!data.WriteInterfaceToken(DataMgrService::GetDescriptor())) { + ZLOGE("write descriptor failed"); + return nullptr; + } + + if (!ITypesUtil::Marshal(data, name)) { + ZLOGE("write descriptor failed"); + return nullptr; + } + + MessageParcel reply; + MessageOption mo{ MessageOption::TF_SYNC }; + int32_t error = Remote()->SendRequest(GET_FEATURE_INTERFACE, data, reply, mo); + if (error != 0) { + ZLOGE("SendRequest returned %{public}d", error); + return nullptr; + } + + sptr remoteObject; + if (!ITypesUtil::Unmarshal(reply, remoteObject)) { + ZLOGE("remote object is nullptr"); + return nullptr; + } + return remoteObject; } } // namespace OHOS::CloudData \ No newline at end of file diff --git a/relational_store/frameworks/native/cloud_data/src/cloud_manager_impl.cpp b/relational_store/frameworks/native/cloud_data/src/cloud_manager_impl.cpp deleted file mode 100644 index f74edb1d..00000000 --- a/relational_store/frameworks/native/cloud_data/src/cloud_manager_impl.cpp +++ /dev/null @@ -1,122 +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. - */ - -#define LOG_TAG "CloudManagerImpl" - -#include "cloud_manager_impl.h" -#include "itypes_util.h" -#include "iservice_registry.h" -#include "log_print.h" -#include "system_ability_definition.h" - -namespace OHOS::CloudData { -CloudManagerImpl &CloudManagerImpl::GetInstance() -{ - static CloudManagerImpl instance; - return instance; -} - -std::shared_ptr CloudManagerImpl::GetCloudService() -{ - std::lock_guard lg(mutex_); - if (cloudService_ != nullptr) { - return cloudService_; - } - auto proxy = GetCloudServiceProxy(); - if (proxy == nullptr) { - return nullptr; - } - cloudService_ = std::shared_ptr(proxy.GetRefPtr(), [holder = proxy] (const auto*) {}); - if (cloudService_ == nullptr) { - return nullptr; - } - return cloudService_; -} - -sptr CloudManagerImpl::GetCloudServiceProxy() -{ - if (distributedDataMgr_ == nullptr) { - distributedDataMgr_ = GetDistributedDataManager(); - } - if (distributedDataMgr_ == nullptr) { - ZLOGE("get distributed data manager failed"); - return nullptr; - } - - auto remote = distributedDataMgr_->GetFeatureInterface(CloudService::SERVICE_NAME); - if (remote == nullptr) { - ZLOGE("get cloud service failed"); - return nullptr; - } - return iface_cast(remote); -} - -CloudDataServiceProxy::CloudDataServiceProxy(const sptr &impl) - : IRemoteProxy(impl) -{ - ZLOGI("init proxy"); -} - -std::shared_ptr CloudManagerImpl::GetDistributedDataManager() -{ - auto abilityMgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); - if (abilityMgr == nullptr) { - ZLOGE("get system ability manager failed"); - return nullptr; - } - auto remoteObject = abilityMgr->CheckSystemAbility(DISTRIBUTED_KV_DATA_SERVICE_ABILITY_ID); - if (remoteObject == nullptr) { - ZLOGE("get distributed data manager failed"); - return nullptr; - } - sptr proxy = new(std::nothrow) CloudDataServiceProxy(remoteObject); - if (proxy == nullptr) { - ZLOGE("new CloudDataServiceProxy failed"); - return nullptr; - } - return std::shared_ptr(proxy.GetRefPtr(), - [holder = proxy](const auto *) {}); -} - -sptr CloudDataServiceProxy::GetFeatureInterface(const std::string &name) -{ - ZLOGI("%s", name.c_str()); - MessageParcel data; - if (!data.WriteInterfaceToken(CloudDataServiceProxy::GetDescriptor())) { - ZLOGE("write descriptor failed"); - return nullptr; - } - - if (!ITypesUtil::Marshal(data, name)) { - ZLOGE("write descriptor failed"); - return nullptr; - } - - MessageParcel reply; - MessageOption mo { MessageOption::TF_SYNC }; - int32_t error = Remote()->SendRequest(GET_FEATURE_INTERFACE, data, reply, mo); - if (error != 0) { - ZLOGE("SendRequest returned %{public}d", error); - return nullptr; - } - - sptr remoteObject; - if (!ITypesUtil::Unmarshal(reply, remoteObject)) { - ZLOGE("remote object is nullptr"); - return nullptr; - } - return remoteObject; -} -} // namespace OHOS::CloudData \ No newline at end of file diff --git a/relational_store/interfaces/inner_api/cloud_data/include/cloud_manager.h b/relational_store/interfaces/inner_api/cloud_data/include/cloud_manager.h index b17c49de..8dcc165f 100644 --- a/relational_store/interfaces/inner_api/cloud_data/include/cloud_manager.h +++ b/relational_store/interfaces/inner_api/cloud_data/include/cloud_manager.h @@ -13,21 +13,23 @@ * limitations under the License. */ -#ifndef OHOS_DISTRIBUTED_DATA_CLOUD_CLOUD_MANAGER_H -#define OHOS_DISTRIBUTED_DATA_CLOUD_CLOUD_MANAGER_H - -#include +#ifndef OHOS_DISTRIBUTED_DATA_CLOUD_CLOUD_MANAGER_IMPL_H +#define OHOS_DISTRIBUTED_DATA_CLOUD_CLOUD_MANAGER_IMPL_H #include -#include "cloud_service.h" -#include "rdb_visibility.h" +#include +#include "cloud_service.h" namespace OHOS::CloudData { -class RDB_API_EXPORT CloudManager final { +class CloudManager { public: - /** - * @brief Obtain cloud service. - */ - static std::shared_ptr GetCloudService(); + static CloudManager &GetInstance(); + std::shared_ptr GetCloudService(); + +private: + CloudManager() = default; + ~CloudManager() = default; + std::mutex mutex_; + std::shared_ptr cloudService_; }; } // namespace OHOS::CloudData -#endif // OHOS_DISTRIBUTED_DATA_CLOUD_CLOUD_MANAGER_H +#endif // OHOS_DISTRIBUTED_DATA_CLOUD_CLOUD_MANAGER_IMPL_H -- Gitee From d00e67639c6857e03420e6736bb7464991bfeeb3 Mon Sep 17 00:00:00 2001 From: Sven Wang Date: Wed, 19 Apr 2023 15:18:38 +0800 Subject: [PATCH 17/44] update Signed-off-by: Sven Wang --- .../innerkitsimpl/include/adaptor/hitrace.h | 6 +- .../include/communicator/app_device_handler.h | 2 +- .../include/communicator/dev_manager.h | 2 + .../include/communicator/softbus_adapter.h | 3 +- .../src/adaptor/distributed_object_impl.cpp | 8 +- .../adaptor/distributed_object_store_impl.cpp | 12 +- .../src/adaptor/flat_object_store.cpp | 25 +- .../src/communicator/app_device_handler.cpp | 4 +- .../src/communicator/dev_manager.cpp | 24 +- .../communicator/softbus_adapter_standard.cpp | 78 +- .../test/unittest/src/communicator_test.cpp | 11 +- .../test/unittest/src/object_store_test.cpp | 95 +- .../jskitsimpl/include/adaptor/js_common.h | 26 + .../jskitsimpl/include/common/object_error.h | 8 + .../src/adaptor/js_distributedobject.cpp | 56 +- .../src/adaptor/js_distributedobjectstore.cpp | 6 +- .../jskitsimpl/src/adaptor/js_watcher.cpp | 24 +- .../jskitsimpl/src/common/object_error.cpp | 10 + .../unittest/src/ObjectStoreJsunit.test.js | 188 +++- .../unittest/src/ObjectStoreJsunitV9.test.js | 224 ++-- data_object/interfaces/jskits/BUILD.gn | 1 + .../jskits/distributed_data_object.js | 529 +++++----- .../samples/distributedNotepad/ReadMe.md | 14 +- .../entry/src/main/js/MainAbility/app.js | 12 +- .../src/main/js/MainAbility/pages/add/add.js | 52 +- .../js/MainAbility/pages/detail/detail.js | 70 +- .../main/js/MainAbility/pages/index/index.js | 120 +-- .../src/main/js/model/DistributedDataModel.js | 170 +-- .../common/src/datashare_predicates_proxy.cpp | 6 +- .../common/src/datashare_result_set_proxy.cpp | 6 +- .../frameworks/js/napi/dataShare/BUILD.gn | 2 + .../include/napi_datashare_inner_observer.h | 33 +- .../include/napi_datashare_observer.h | 19 +- .../js/napi/dataShare/src/async_call.cpp | 2 +- .../dataShare/src/napi_datashare_helper.cpp | 17 +- .../src/napi_datashare_inner_observer.cpp | 100 ++ .../dataShare/src/napi_datashare_observer.cpp | 74 +- .../datashare_ext_ability.js | 74 +- .../datashare_ext_ability_context.js | 10 +- .../native/common/include/adaptor.h | 2 +- .../common/src/ishared_result_set_proxy.cpp | 2 - .../native/consumer/include/base_connection.h | 6 +- .../consumer/include/datashare_connection.h | 18 +- .../consumer/src/connection_factory.cpp | 7 +- .../consumer/src/datashare_connection.cpp | 39 +- .../native/consumer/src/datashare_proxy.cpp | 2 +- .../provider/include/datashare_ext_ability.h | 6 +- .../include/js_datashare_ext_ability.h | 2 +- .../provider/src/datashare_ext_ability.cpp | 2 +- .../native/provider/src/datashare_stub.cpp | 3 + .../provider/src/datashare_stub_impl.cpp | 8 +- .../provider/src/datashare_uv_queue.cpp | 2 +- .../provider/src/js_datashare_ext_ability.cpp | 15 +- .../src/js_datashare_ext_ability_context.cpp | 2 +- .../proxy/include/data_share_manager_impl.h | 3 +- .../proxy/src/data_share_manager_impl.cpp | 11 +- data_share/interfaces/inner_api/BUILD.gn | 7 +- .../common/include/datashare_predicates.h | 2 +- data_share/test/native/BUILD.gn | 2 +- .../src/mediadatashare_unit_test.cpp | 2 +- datamgr_service/conf/config.json | 3 + .../distributeddataservice/adapter/BUILD.gn | 1 + .../adapter/account/BUILD.gn | 1 + .../adapter/account/test/BUILD.gn | 1 + .../adapter/autils/BUILD.gn | 1 + .../adapter/autils/test/BUILD.gn | 1 + .../adapter/broadcaster/BUILD.gn | 1 + .../adapter/communicator/BUILD.gn | 1 + .../adapter/communicator/src/data_buffer.cpp | 2 +- .../src/device_manager_adapter.cpp | 18 +- .../adapter/communicator/test/BUILD.gn | 2 + .../adapter/dfx/BUILD.gn | 1 + .../adapter/dfx/test/BUILD.gn | 2 + .../communicator/device_manager_adapter.h | 2 + .../adapter/permission/BUILD.gn | 1 + .../adapter/permission/test/BUILD.gn | 1 + .../adapter/utils/BUILD.gn | 1 + .../distributeddataservice/app/BUILD.gn | 1 + .../app/src/checker/BUILD.gn | 1 + .../app/src/flowctrl_manager/BUILD.gn | 1 + .../app/src/kvstore_data_service.cpp | 15 + .../src/session_manager/upgrade_manager.cpp | 9 +- .../app/src/session_manager/upgrade_manager.h | 2 +- .../app/src/uninstaller/BUILD.gn | 1 + .../app/src/uninstaller/uninstaller_impl.cpp | 5 +- .../distributeddataservice/app/test/BUILD.gn | 60 +- .../test/unittest/session_manager_test.cpp | 2 +- .../distributeddataservice/framework/BUILD.gn | 1 + .../backuprule/backup_rule_manager.cpp | 8 +- .../framework/checker/checker_manager.cpp | 8 +- .../framework/include/cloud/asset_loader.h | 2 +- .../include/metadata/store_meta_data.h | 3 +- .../framework/include/store/auto_cache.h | 9 +- .../framework/include/store/cursor.h | 30 +- .../framework/include/store/general_store.h | 16 +- .../framework/include/store/general_value.h | 93 ++ .../framework/include/store/general_watcher.h | 12 +- .../framework/store/auto_cache.cpp | 4 +- .../framework/test/BUILD.gn | 1 + .../framework/test/serializable_test.cpp | 11 +- .../distributeddataservice/service/BUILD.gn | 1 + .../service/bootstrap/src/bootstrap.cpp | 7 +- .../data_share/data_share_profile_info.cpp | 57 +- .../data_share/data_share_profile_info.h | 8 +- .../data_share/data_share_service_impl.cpp | 5 +- .../service/data_share/permission_proxy.cpp | 15 +- .../service/data_share/permission_proxy.h | 6 +- .../service/data_share/rdb_adaptor.h | 2 +- .../service/data_share/uri_utils.cpp | 20 +- .../service/data_share/uri_utils.h | 14 +- .../directory/src/directory_manager.cpp | 2 +- .../service/kvdb/kvdb_service_impl.cpp | 31 - .../service/kvdb/kvdb_service_impl.h | 4 +- .../service/kvdb/kvdb_service_stub.cpp | 33 - .../service/kvdb/kvdb_service_stub.h | 2 - .../service/kvdb/upgrade.cpp | 53 + .../service/kvdb/upgrade.h | 8 + .../service/kvdb/user_delegate.cpp | 70 +- .../service/kvdb/user_delegate.h | 3 +- .../service/rdb/irdb_result_set.h | 4 +- .../service/rdb/rdb_service_impl.cpp | 30 +- .../service/rdb/rdb_service_impl.h | 2 - .../service/rdb/rdb_syncer.cpp | 33 +- .../service/rdb/rdb_syncer.h | 2 +- .../service/test/BUILD.gn | 5 +- .../service/test/config_factory_test.cpp | 2 +- .../service/test/mock/db_store_mock.cpp | 5 + .../service/test/mock/db_store_mock.h | 2 + .../test/fuzztest/schemaquery_fuzzer/BUILD.gn | 1 + .../test/fuzztest/autolaunch_fuzzer/BUILD.gn | 1 + .../fuzztest/kvstoredisksize_fuzzer/BUILD.gn | 1 + kv_store/frameworks/common/executor.h | 131 +++ kv_store/frameworks/common/executor_pool.h | 256 +++-- kv_store/frameworks/common/pool.h | 87 +- kv_store/frameworks/common/priority_queue.h | 122 +++ kv_store/frameworks/common/task_scheduler.h | 22 +- .../common/test/concurrent_map_test.cpp | 2 +- .../common/test/lru_bucket_test.cpp | 5 +- .../common/test/task_scheduler_test.cpp | 126 ++- .../test/unittest/device_kvstore_test.cpp | 2 +- .../distributed_kv_data_manager_test.cpp | 14 - .../innerkitsimpl/kvdb/include/dev_manager.h | 2 +- .../innerkitsimpl/kvdb/include/kvdb_service.h | 8 +- .../kvdb/include/kvdb_service_client.h | 2 - .../kvdb/include/observer_bridge.h | 1 + .../kvdb/include/single_store_impl.h | 9 +- .../kvdb/include/task_executor.h | 3 +- .../innerkitsimpl/kvdb/src/dev_manager.cpp | 41 +- .../kvdb/src/kvdb_service_client.cpp | 30 +- .../kvdb/src/observer_bridge.cpp | 8 + .../kvdb/src/security_manager.cpp | 14 +- .../kvdb/src/single_store_impl.cpp | 55 +- .../innerkitsimpl/kvdb/src/store_factory.cpp | 3 + .../innerkitsimpl/kvdb/src/task_executor.cpp | 15 +- .../kvdb/test/single_store_impl_test.cpp | 10 +- .../kvdb/test/store_factory_test.cpp | 8 +- .../src/js_device_kv_store.cpp | 2 + .../distributeddata/src/js_kv_manager.cpp | 1 + .../src/js_single_kv_store.cpp | 2 + .../src/js_device_kv_store.cpp | 4 + .../distributedkvstore/src/js_error_utils.cpp | 3 +- .../distributedkvstore/src/js_kv_manager.cpp | 2 +- .../src/js_single_kv_store.cpp | 2 + .../frameworks/libs/distributeddb/BUILD.gn | 1 + .../distributeddb/common/include/db_common.h | 7 + .../common/include/db_constant.h | 2 + .../distributeddb/common/include/db_errno.h | 1 + .../distributeddb/common/include/db_types.h | 4 +- .../common/include/runtime_context.h | 7 + .../distributeddb/common/src/auto_launch.cpp | 16 +- .../distributeddb/common/src/data_value.cpp | 4 +- .../distributeddb/common/src/db_common.cpp | 26 +- .../common/src/runtime_context_impl.cpp | 30 + .../common/src/runtime_context_impl.h | 10 + .../src/communicator_aggregator.cpp | 11 + .../communicator/src/network_adapter.cpp | 4 + .../communicator/src/protocol_proto.cpp | 38 +- .../communicator/src/protocol_proto.h | 4 + .../libs/distributeddb/distributeddb.gni | 1 + .../libs/distributeddb/include/types_export.h | 7 + .../interfaces/include/kv_store_nb_delegate.h | 3 + .../relational/relational_store_delegate.h | 3 + .../interfaces/include/runtime_config.h | 1 + .../interfaces/include/store_types.h | 5 + .../interfaces/src/kv_store_errno.cpp | 1 + .../src/kv_store_nb_delegate_impl.cpp | 18 + .../src/kv_store_nb_delegate_impl.h | 2 + .../relational_store_delegate_impl.cpp | 15 + .../relational_store_delegate_impl.h | 2 + .../relational/relational_store_manager.cpp | 2 +- .../interfaces/src/runtime_config.cpp | 5 + .../storage/include/ikvdb_connection.h | 2 + .../storage/include/kvdb_manager.h | 4 + .../include/relational_store_connection.h | 1 + .../storage/src/generic_kvdb_connection.cpp | 5 + .../storage/src/generic_kvdb_connection.h | 2 + .../storage/src/kvdb_manager.cpp | 66 +- .../src/relational_sync_able_storage.cpp | 17 +- .../src/relational_sync_data_inserter.cpp | 18 +- .../src/relational_sync_data_inserter.h | 10 +- .../relational/sqlite_relational_store.cpp | 203 +++- .../relational/sqlite_relational_store.h | 12 + .../sqlite_relational_store_connection.cpp | 15 + .../sqlite_relational_store_connection.h | 1 + .../src/sqlite/sqlite_meta_executor.cpp | 113 ++ .../storage/src/sqlite/sqlite_meta_executor.h | 47 + .../src/sqlite/sqlite_query_helper.cpp | 15 +- .../sqlite_single_ver_natural_store.cpp | 122 ++- .../sqlite/sqlite_single_ver_natural_store.h | 6 +- ...te_single_ver_natural_store_connection.cpp | 26 + ...lite_single_ver_natural_store_connection.h | 1 + ...single_ver_relational_storage_executor.cpp | 85 +- ...e_single_ver_relational_storage_executor.h | 6 +- .../sqlite_single_ver_storage_engine.cpp | 2 +- .../sqlite_single_ver_storage_executor.cpp | 166 +-- .../sqlite_single_ver_storage_executor.h | 23 +- ...lite_single_ver_storage_executor_cache.cpp | 7 +- .../sqlite_single_ver_storage_executor_sql.h | 7 + .../storage/src/sqlite/sqlite_utils.cpp | 45 +- .../storage/src/storage_engine.cpp | 88 +- .../storage/src/storage_engine.h | 4 + .../storage/src/sync_able_engine.cpp | 30 +- .../storage/src/sync_able_engine.h | 4 + .../storage/src/sync_able_kvdb.cpp | 35 +- .../storage/src/sync_able_kvdb.h | 4 + .../distributeddb/syncer/include/isyncer.h | 2 + .../syncer/include/syncer_proxy.h | 1 + .../syncer/src/generic_syncer.cpp | 75 +- .../distributeddb/syncer/src/generic_syncer.h | 4 +- .../syncer/src/isync_task_context.h | 2 +- .../distributeddb/syncer/src/meta_data.cpp | 70 +- .../libs/distributeddb/syncer/src/meta_data.h | 17 +- .../src/query_sync_water_mark_helper.cpp | 26 +- .../syncer/src/query_sync_water_mark_helper.h | 6 +- .../syncer/src/remote_executor.cpp | 10 +- .../syncer/src/remote_executor.h | 2 +- .../syncer/src/single_ver_data_sync.cpp | 18 +- .../syncer/src/single_ver_kv_syncer.cpp | 38 +- .../syncer/src/single_ver_kv_syncer.h | 3 +- .../src/single_ver_relational_syncer.cpp | 11 +- .../syncer/src/single_ver_relational_syncer.h | 3 +- .../syncer/src/single_ver_serialize_manager.h | 1 + .../src/single_ver_sync_task_context.cpp | 3 + .../syncer/src/single_ver_sync_task_context.h | 3 +- .../syncer/src/single_ver_syncer.cpp | 13 + .../syncer/src/single_ver_syncer.h | 1 + .../distributeddb/syncer/src/sync_engine.cpp | 25 +- .../syncer/src/sync_state_machine.cpp | 5 +- .../syncer/src/sync_task_context.cpp | 16 +- .../syncer/src/sync_task_context.h | 2 +- .../distributeddb/syncer/src/syncer_proxy.cpp | 8 + .../libs/distributeddb/test/BUILD.gn | 2 + .../test/fuzztest/delegate_fuzzer/BUILD.gn | 1 + .../delegate_fuzzer/delegate_fuzzer.cpp | 25 +- .../test/fuzztest/fileoper_fuzzer/BUILD.gn | 1 + .../test/fuzztest/importfile_fuzzer/BUILD.gn | 1 + .../iprocesscommunicator_fuzzer/BUILD.gn | 1 + .../kvdelegatemanager_fuzzer/BUILD.gn | 1 + .../fuzztest/kvstoreresultset_fuzzer/BUILD.gn | 1 + .../test/fuzztest/nbdelegate_fuzzer/BUILD.gn | 1 + .../nbdelegate_fuzzer/nbdelegate_fuzzer.cpp | 32 +- .../test/fuzztest/parseckeck_fuzzer/BUILD.gn | 1 + .../test/fuzztest/query_fuzzer/BUILD.gn | 1 + .../test/fuzztest/rekey_fuzzer/BUILD.gn | 1 + .../relationalstoredelegate_fuzzer/BUILD.gn | 1 + .../relationalstoredelegate_fuzzer.cpp | 3 +- .../relationalstoremanager_fuzzer/BUILD.gn | 1 + .../relationalstoremanager_fuzzer.cpp | 3 + .../fuzztest/schemadelegate_fuzzer/BUILD.gn | 1 + .../test/fuzztest/sync_fuzzer/BUILD.gn | 1 + .../distributeddb/test/moduletest/BUILD.gn | 1 + .../src/distributeddb_kv_crud_test.cpp | 27 +- .../src/distributeddb_nb_create_test.cpp | 39 - .../distributeddb_communicator_deep_test.cpp | 13 + ...distributeddb_interfaces_database_test.cpp | 100 +- ...eddb_interfaces_device_identifier_test.cpp | 19 +- ...teddb_interfaces_encrypt_delegate_test.cpp | 11 - ...tributeddb_interfaces_nb_delegate_test.cpp | 214 +++- ...uteddb_interfaces_relational_sync_test.cpp | 171 ++++ ...stributeddb_interfaces_relational_test.cpp | 168 ++- ...t_process_system_api_adapter_impl_test.cpp | 29 +- ...distributeddb_relational_get_data_test.cpp | 30 +- ...torage_single_ver_natural_store_testcase.h | 4 +- ...qlite_single_ver_natural_executor_test.cpp | 9 +- ...ributeddb_storage_subscribe_query_test.cpp | 46 + .../distributeddb_mock_sync_module_test.cpp | 494 ++++++--- ...stributeddb_relational_multi_user_test.cpp | 59 +- ...ributeddb_relational_ver_p2p_sync_test.cpp | 249 +++-- ...stributeddb_single_ver_multi_user_test.cpp | 59 +- ...teddb_single_ver_p2p_complex_sync_test.cpp | 186 +++- ...db_single_ver_p2p_permission_sync_test.cpp | 48 + ...buteddb_single_ver_p2p_query_sync_test.cpp | 101 +- ...ddb_single_ver_p2p_subscribe_sync_test.cpp | 65 +- .../common/syncer/mock_remote_executor.h | 4 +- .../common/syncer/mock_sync_task_context.h | 5 + .../virtual_communicator_aggregator.cpp | 10 + .../syncer/virtual_communicator_aggregator.h | 2 + .../virtual_single_ver_sync_db_Interface.cpp | 15 +- .../innerkits/distributeddata/BUILD.gn | 3 +- .../innerkits/distributeddata/include/blob.h | 31 + .../include/change_notification.h | 3 + .../distributeddata/include/data_query.h | 6 + .../include/distributed_kv_data_manager.h | 6 + .../distributeddata/include/kvstore.h | 14 +- .../include/kvstore_observer.h | 6 + .../include/kvstore_result_set.h | 4 + .../include/kvstore_sync_callback.h | 6 + .../distributeddata/include/single_kvstore.h | 6 + .../innerkits/distributeddata/include/types.h | 28 +- .../jskits/distributeddata/BUILD.gn | 1 + .../jskits/distributedkvstore/BUILD.gn | 1 + kv_store/kvstoremock/distributeddb/BUILD.gn | 1 + .../test/fuzztest/typesutil_fuzzer/BUILD.gn | 2 +- .../SingleKvStoreDataCallbackJsTest.js | 21 - .../SingleKvStoreDataPromiseJsTest.js | 23 - .../runtime/include/js_runtime.h | 2 + .../include/bundle_common_event.h | 22 +- .../devicemanagersdk/include/device_manager.h | 5 +- .../include/device_manager_impl.h | 2 + mock/src/mock_device_manager.cpp | 7 + mock/src/mock_js_runtime.cpp | 5 + .../frameworks/js/napi/preferences/BUILD.gn | 1 + .../napi/preferences/src/napi_preferences.cpp | 11 +- .../js/napi/storage/src/napi_storage.cpp | 18 +- .../napi/storage/src/napi_storage_helper.cpp | 12 +- .../js/napi/system_storage/BUILD.gn | 1 + .../src/napi_system_storage.cpp | 6 +- .../native/include/preferences_impl.h | 10 +- .../frameworks/native/include/task_executor.h | 35 + .../native/include/task_scheduler.h | 127 +++ .../frameworks/native/include/visibility.h | 12 +- .../native/src/preferences_helper.cpp | 1 + .../native/src/preferences_impl.cpp | 50 +- .../frameworks/native/src/task_executor.cpp | 43 + preferences/interfaces/inner_api/BUILD.gn | 3 +- .../test/native/unittest/preferences_test.cpp | 2 +- .../unittest/preferences_xml_utils_test.cpp | 8 +- relational_store/bundle.json | 3 +- .../frameworks/js/napi/rdb/BUILD.gn | 1 + .../js/napi/rdb/src/napi_rdb_store.cpp | 2 +- .../js/napi/relationalstore/BUILD.gn | 1 + .../relationalstore/include/napi_rdb_error.h | 2 +- .../relationalstore/include/napi_result_set.h | 1 + .../mock/include/napi_result_set.h | 1 + .../relationalstore/src/napi_async_call.cpp | 2 +- .../relationalstore/src/napi_result_set.cpp | 35 +- .../native/rdb/include/result_set_proxy.h | 1 + .../native/rdb/include/sqlite_global_config.h | 1 + .../rdb/mock/include/sqlite_global_config.h | 1 + .../native/rdb/src/abs_result_set.cpp | 89 ++ .../native/rdb/src/rdb_store_impl.cpp | 8 +- .../native/rdb/src/rdb_store_manager.cpp | 2 +- .../native/rdb/src/result_set_proxy.cpp | 5 + .../native/rdb/src/store_session.cpp | 447 ++++++++ .../inner_api/rdb/include/abs_result_set.h | 6 + .../inner_api/rdb/include/rdb_errno.h | 8 +- .../inner_api/rdb/include/remote_result_set.h | 304 ++++++ .../inner_api/rdb/include/result_set.h | 279 +---- .../rdb/mock/include/abs_result_set.h | 77 ++ .../inner_api/rdb/mock/include/result_set.h | 40 +- .../inner_api/rdb/mock/include/value_object.h | 13 +- relational_store/test/js/rdb/BUILD.gn | 7 + .../test/js/rdb/performance/config.json | 62 ++ .../js/rdb/performance/openharmony_sx.p7b | Bin 0 -> 3437 bytes .../test/js/rdb/performance/src/BUILD.gn | 24 + .../js/rdb/performance/src/PredicatestPerf.js | 506 +++++++++ .../performance/src/RdbHelperCallbackPerf.js | 93 ++ .../performance/src/RdbHelperPromisePerf.js | 78 ++ .../performance/src/RdbStoreCallbackPerf.js | 125 +++ .../src/RdbStoreOthersCallbackPerf.js | 165 +++ .../performance/src/RdbStorePromisePerf.js | 86 ++ .../rdb/performance/src/RdbStoreSyncPerf.js | 98 ++ .../js/rdb/performance/src/ResultSetPerf.js | 288 ++++++ ...reBackupRestoreWithFAContextJsunit.test.js | 245 +++++ .../test/js/relationalstore/BUILD.gn | 7 + .../relationalstore/performance/src/BUILD.gn | 4 +- .../performance/src/PredicatestPerf.js | 967 +++++++++--------- .../performance/src/RdbHelperCallbackPerf.js | 108 +- .../performance/src/RdbHelperPromisePerf.js | 90 +- .../performance/src/RdbStoreCallbackPerf.js | 161 +-- .../src/RdbStoreOthersCallbackPerf.js | 245 ++--- .../performance/src/RdbStorePromisePerf.js | 99 +- .../performance/src/RdbStoreSyncPerf.js | 122 ++- .../performance/src/ResultSetPerf.js | 481 +++++---- .../src/SceneGetValuesBucketPerf.js | 197 ++++ .../src/RdbStoreResultSetGetRow.test.js | 182 ++++ .../src/RdbStoreResultSetJsunit.test.js | 42 +- relational_store/test/native/rdb/BUILD.gn | 1 + .../native/rdb/unittest/rdb_execute_test.cpp | 2 - .../rdb_sqlite_shared_result_set_test.cpp | 74 +- .../unittest/rdb_step_result_get_row_test.cpp | 254 +++++ .../rdb/unittest/rdb_step_result_set_test.cpp | 110 +- .../rdb/unittest/rdb_store_rekey_test.cpp | 48 +- .../rdb/unittest/rdb_transaction_test.cpp | 5 +- .../rdb/unittest/rdb_value_bucket_test.cpp | 2 +- .../unittest/rdb_data_share_adapter_test.cpp | 6 - 396 files changed, 10790 insertions(+), 4134 deletions(-) rename datamgr_service/services/distributeddataservice/framework/store/cursor.cpp => data_share/frameworks/js/napi/dataShare/include/napi_datashare_inner_observer.h (40%) create mode 100644 data_share/frameworks/js/napi/dataShare/src/napi_datashare_inner_observer.cpp create mode 100644 datamgr_service/services/distributeddataservice/framework/include/store/general_value.h create mode 100644 kv_store/frameworks/common/executor.h create mode 100644 kv_store/frameworks/common/priority_queue.h create mode 100644 kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_meta_executor.cpp create mode 100644 kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_meta_executor.h rename datamgr_service/services/distributeddataservice/framework/store/general_watcher.cpp => mock/innerkits/appexecfwk_base/include/bundle_common_event.h (39%) create mode 100644 preferences/frameworks/native/include/task_executor.h create mode 100644 preferences/frameworks/native/include/task_scheduler.h rename datamgr_service/services/distributeddataservice/framework/store/asset.cpp => preferences/frameworks/native/include/visibility.h (64%) create mode 100644 preferences/frameworks/native/src/task_executor.cpp create mode 100644 relational_store/frameworks/native/rdb/src/store_session.cpp create mode 100644 relational_store/interfaces/inner_api/rdb/include/remote_result_set.h create mode 100644 relational_store/interfaces/inner_api/rdb/mock/include/abs_result_set.h rename datamgr_service/services/distributeddataservice/framework/include/store/asset.h => relational_store/interfaces/inner_api/rdb/mock/include/result_set.h (45%) create mode 100644 relational_store/test/js/rdb/performance/config.json create mode 100644 relational_store/test/js/rdb/performance/openharmony_sx.p7b create mode 100644 relational_store/test/js/rdb/performance/src/BUILD.gn create mode 100644 relational_store/test/js/rdb/performance/src/PredicatestPerf.js create mode 100644 relational_store/test/js/rdb/performance/src/RdbHelperCallbackPerf.js create mode 100644 relational_store/test/js/rdb/performance/src/RdbHelperPromisePerf.js create mode 100644 relational_store/test/js/rdb/performance/src/RdbStoreCallbackPerf.js create mode 100644 relational_store/test/js/rdb/performance/src/RdbStoreOthersCallbackPerf.js create mode 100644 relational_store/test/js/rdb/performance/src/RdbStorePromisePerf.js create mode 100644 relational_store/test/js/rdb/performance/src/RdbStoreSyncPerf.js create mode 100644 relational_store/test/js/rdb/performance/src/ResultSetPerf.js create mode 100644 relational_store/test/js/rdb/unittest/src/RdbstoreBackupRestoreWithFAContextJsunit.test.js create mode 100644 relational_store/test/js/relationalstore/performance/src/SceneGetValuesBucketPerf.js create mode 100644 relational_store/test/js/relationalstore/unittest/src/RdbStoreResultSetGetRow.test.js create mode 100644 relational_store/test/native/rdb/unittest/rdb_step_result_get_row_test.cpp diff --git a/data_object/frameworks/innerkitsimpl/include/adaptor/hitrace.h b/data_object/frameworks/innerkitsimpl/include/adaptor/hitrace.h index 85ac55e8..7ceb5980 100644 --- a/data_object/frameworks/innerkitsimpl/include/adaptor/hitrace.h +++ b/data_object/frameworks/innerkitsimpl/include/adaptor/hitrace.h @@ -19,14 +19,14 @@ namespace OHOS { namespace ObjectStore { -class HiTrace final { +class DataObjectHiTrace final { public: - inline HiTrace(const std::string &value) + inline DataObjectHiTrace(const std::string &value) { StartTrace(HITRACE_TAG_DISTRIBUTEDDATA, value); } - inline ~HiTrace() + inline ~DataObjectHiTrace() { FinishTrace(HITRACE_TAG_DISTRIBUTEDDATA); } diff --git a/data_object/frameworks/innerkitsimpl/include/communicator/app_device_handler.h b/data_object/frameworks/innerkitsimpl/include/communicator/app_device_handler.h index 0bca19bb..f32a906b 100644 --- a/data_object/frameworks/innerkitsimpl/include/communicator/app_device_handler.h +++ b/data_object/frameworks/innerkitsimpl/include/communicator/app_device_handler.h @@ -34,7 +34,7 @@ public: DeviceInfo GetLocalDevice(); std::vector GetDeviceList() const; - std::string GetUdidByNodeId(const std::string &nodeId) const; + std::string GetUuidByNodeId(const std::string &nodeId) const; // get local device node information; DeviceInfo GetLocalBasicInfo() const; // get all remote connected device's node information; diff --git a/data_object/frameworks/innerkitsimpl/include/communicator/dev_manager.h b/data_object/frameworks/innerkitsimpl/include/communicator/dev_manager.h index 166e7f15..ce686389 100644 --- a/data_object/frameworks/innerkitsimpl/include/communicator/dev_manager.h +++ b/data_object/frameworks/innerkitsimpl/include/communicator/dev_manager.h @@ -15,6 +15,7 @@ #ifndef DATA_OBJECT_DEV_MANAGER_H #define DATA_OBJECT_DEV_MANAGER_H #include +#include namespace OHOS { namespace ObjectStore { class DevManager { @@ -25,6 +26,7 @@ public: return instance; } void RegisterDevCallback(); + std::string GetUuidByNodeId(const std::string &nodeId) const; private: DevManager(); diff --git a/data_object/frameworks/innerkitsimpl/include/communicator/softbus_adapter.h b/data_object/frameworks/innerkitsimpl/include/communicator/softbus_adapter.h index 54714fea..93d9fb48 100644 --- a/data_object/frameworks/innerkitsimpl/include/communicator/softbus_adapter.h +++ b/data_object/frameworks/innerkitsimpl/include/communicator/softbus_adapter.h @@ -45,7 +45,6 @@ public: void NotifyAll(const DeviceInfo &deviceInfo, const DeviceChangeType &type); DeviceInfo GetLocalDevice(); std::vector GetDeviceList() const; - std::string GetUdidByNodeId(const std::string &nodeId) const; // get local device node information; DeviceInfo GetLocalBasicInfo() const; // get all remote connected device's node information; @@ -92,7 +91,7 @@ private: }; std::shared_ptr> GetSemaphore (int32_t sessinId); mutable std::mutex networkMutex_{}; - mutable std::map networkId2Udid_{}; + mutable std::map networkId2Uuid_{}; DeviceInfo localInfo_{}; static std::shared_ptr instance_; std::mutex deviceChangeMutex_; diff --git a/data_object/frameworks/innerkitsimpl/src/adaptor/distributed_object_impl.cpp b/data_object/frameworks/innerkitsimpl/src/adaptor/distributed_object_impl.cpp index 1e1722ab..d7c0e464 100644 --- a/data_object/frameworks/innerkitsimpl/src/adaptor/distributed_object_impl.cpp +++ b/data_object/frameworks/innerkitsimpl/src/adaptor/distributed_object_impl.cpp @@ -55,7 +55,7 @@ uint32_t GetNum(Bytes &data, uint32_t offset, void *val, uint32_t valLen) uint32_t DistributedObjectImpl::PutDouble(const std::string &key, double value) { - HiTrace trace(std::string(__FUNCTION__)); + DataObjectHiTrace trace(std::string(__FUNCTION__)); Bytes data; Type type = Type::TYPE_DOUBLE; PutNum(&type, 0, sizeof(type), data); @@ -69,7 +69,7 @@ uint32_t DistributedObjectImpl::PutDouble(const std::string &key, double value) uint32_t DistributedObjectImpl::PutBoolean(const std::string &key, bool value) { - HiTrace trace(std::string(__FUNCTION__)); + DataObjectHiTrace trace(std::string(__FUNCTION__)); Bytes data; Type type = Type::TYPE_BOOLEAN; PutNum(&type, 0, sizeof(type), data); @@ -83,7 +83,7 @@ uint32_t DistributedObjectImpl::PutBoolean(const std::string &key, bool value) uint32_t DistributedObjectImpl::PutString(const std::string &key, const std::string &value) { - HiTrace trace(std::string(__FUNCTION__)); + DataObjectHiTrace trace(std::string(__FUNCTION__)); Bytes data; Type type = Type::TYPE_STRING; PutNum(&type, 0, sizeof(type), data); @@ -172,7 +172,7 @@ DistributedObjectImpl::DistributedObjectImpl(const std::string &sessionId, FlatO uint32_t DistributedObjectImpl::PutComplex(const std::string &key, const std::vector &value) { - HiTrace trace(std::string(__FUNCTION__)); + DataObjectHiTrace trace(std::string(__FUNCTION__)); Bytes data; Type type = Type::TYPE_COMPLEX; PutNum(&type, 0, sizeof(type), data); diff --git a/data_object/frameworks/innerkitsimpl/src/adaptor/distributed_object_store_impl.cpp b/data_object/frameworks/innerkitsimpl/src/adaptor/distributed_object_store_impl.cpp index 51077823..c99c4019 100644 --- a/data_object/frameworks/innerkitsimpl/src/adaptor/distributed_object_store_impl.cpp +++ b/data_object/frameworks/innerkitsimpl/src/adaptor/distributed_object_store_impl.cpp @@ -62,7 +62,7 @@ void DistributedObjectStoreImpl::RemoveCacheObject(const std::string &sessionId) DistributedObject *DistributedObjectStoreImpl::CreateObject(const std::string &sessionId) { - HiTrace trace(std::string(__FUNCTION__)); + DataObjectHiTrace trace(std::string(__FUNCTION__)); if (flatObjectStore_ == nullptr) { LOG_ERROR("DistributedObjectStoreImpl::CreateObject store not opened!"); return nullptr; @@ -83,7 +83,7 @@ DistributedObject *DistributedObjectStoreImpl::CreateObject(const std::string &s DistributedObject *DistributedObjectStoreImpl::CreateObject(const std::string &sessionId, uint32_t &status) { - HiTrace trace(std::string(__FUNCTION__)); + DataObjectHiTrace trace(std::string(__FUNCTION__)); if (flatObjectStore_ == nullptr) { LOG_ERROR("DistributedObjectStoreImpl::CreateObject store not opened!"); status = ERR_NULL_OBJECTSTORE; @@ -106,7 +106,7 @@ DistributedObject *DistributedObjectStoreImpl::CreateObject(const std::string &s uint32_t DistributedObjectStoreImpl::DeleteObject(const std::string &sessionId) { - HiTrace trace(std::string(__FUNCTION__)); + DataObjectHiTrace trace(std::string(__FUNCTION__)); if (flatObjectStore_ == nullptr) { LOG_ERROR("DistributedObjectStoreImpl::Sync object err "); return ERR_NULL_OBJECTSTORE; @@ -223,7 +223,11 @@ DistributedObjectStore *DistributedObjectStore::GetInstance(const std::string &b } // Use instMemory to make sure this singleton not free before other object. // This operation needn't to malloc memory, we needn't to check nullptr. - instPtr = new DistributedObjectStoreImpl(flatObjectStore); + instPtr = new (std::nothrow) DistributedObjectStoreImpl(flatObjectStore); + if (instPtr == nullptr) { + LOG_ERROR("no memory for DistributedObjectStoreImpl malloc!"); + return nullptr; + } } } return instPtr; diff --git a/data_object/frameworks/innerkitsimpl/src/adaptor/flat_object_store.cpp b/data_object/frameworks/innerkitsimpl/src/adaptor/flat_object_store.cpp index dba081c2..96b87453 100644 --- a/data_object/frameworks/innerkitsimpl/src/adaptor/flat_object_store.cpp +++ b/data_object/frameworks/innerkitsimpl/src/adaptor/flat_object_store.cpp @@ -276,9 +276,13 @@ int32_t CacheManager::SaveObject(const std::string &bundleName, const std::strin sptr proxy = ClientAdaptor::GetObjectService(); if (proxy == nullptr) { LOG_ERROR("proxy is nullptr."); + return ERR_PROCESSING; + } + sptr objectSaveCallback = new (std::nothrow) ObjectSaveCallback(callback); + if (objectSaveCallback == nullptr) { + LOG_ERROR("CacheManager::SaveObject no memory for ObjectSaveCallback malloc!"); return ERR_NULL_PTR; } - sptr objectSaveCallback = new ObjectSaveCallback(callback); int32_t status = proxy->ObjectStoreSave( bundleName, sessionId, deviceId, objectData, objectSaveCallback->AsObject().GetRefPtr()); if (status != SUCCESS) { @@ -294,9 +298,14 @@ int32_t CacheManager::RevokeSaveObject( sptr proxy = ClientAdaptor::GetObjectService(); if (proxy == nullptr) { LOG_ERROR("proxy is nullptr."); + return ERR_PROCESSING; + } + sptr objectRevokeSaveCallback = new (std::nothrow) + ObjectRevokeSaveCallback(callback); + if (objectRevokeSaveCallback == nullptr) { + LOG_ERROR("CacheManager::RevokeSaveObject no memory for ObjectRevokeSaveCallback malloc!"); return ERR_NULL_PTR; } - sptr objectRevokeSaveCallback = new ObjectRevokeSaveCallback(callback); int32_t status = proxy->ObjectStoreRevokeSave( bundleName, sessionId, objectRevokeSaveCallback->AsObject().GetRefPtr()); if (status != SUCCESS) { @@ -314,7 +323,11 @@ int32_t CacheManager::ResumeObject(const std::string &bundleName, const std::str LOG_ERROR("proxy is nullptr."); return ERR_NULL_PTR; } - sptr objectRetrieveCallback = new ObjectRetrieveCallback(callback); + sptr objectRetrieveCallback = new (std::nothrow) ObjectRetrieveCallback(callback); + if (objectRetrieveCallback == nullptr) { + LOG_ERROR("CacheManager::ResumeObject no memory for ObjectRetrieveCallback malloc!"); + return ERR_NULL_PTR; + } int32_t status = proxy->ObjectStoreRetrieve( bundleName, sessionId, objectRetrieveCallback->AsObject().GetRefPtr()); if (status != SUCCESS) { @@ -332,7 +345,11 @@ int32_t CacheManager::SubscribeDataChange(const std::string &bundleName, const s LOG_ERROR("proxy is nullptr."); return ERR_NULL_PTR; } - sptr objectRemoteResumeCallback = new ObjectChangeCallback(callback); + sptr objectRemoteResumeCallback = new (std::nothrow) ObjectChangeCallback(callback); + if (objectRemoteResumeCallback == nullptr) { + LOG_ERROR("CacheManager::SubscribeDataChange no memory for ObjectChangeCallback malloc!"); + return ERR_NULL_PTR; + } ClientAdaptor::RegisterClientDeathListener(bundleName, objectRemoteResumeCallback->AsObject()); int32_t status = proxy->RegisterDataObserver( bundleName, sessionId, objectRemoteResumeCallback->AsObject().GetRefPtr()); diff --git a/data_object/frameworks/innerkitsimpl/src/communicator/app_device_handler.cpp b/data_object/frameworks/innerkitsimpl/src/communicator/app_device_handler.cpp index 9518c61e..3ccfca24 100644 --- a/data_object/frameworks/innerkitsimpl/src/communicator/app_device_handler.cpp +++ b/data_object/frameworks/innerkitsimpl/src/communicator/app_device_handler.cpp @@ -66,9 +66,9 @@ std::vector AppDeviceHandler::GetRemoteNodesBasicInfo() const return softbusAdapter_->GetRemoteNodesBasicInfo(); } -std::string AppDeviceHandler::GetUdidByNodeId(const std::string &nodeId) const +std::string AppDeviceHandler::GetUuidByNodeId(const std::string &nodeId) const { - return softbusAdapter_->GetUdidByNodeId(nodeId); + return devManager_->GetUuidByNodeId(nodeId); } } // namespace ObjectStore } // namespace OHOS diff --git a/data_object/frameworks/innerkitsimpl/src/communicator/dev_manager.cpp b/data_object/frameworks/innerkitsimpl/src/communicator/dev_manager.cpp index ff03a7cf..0d6442f4 100644 --- a/data_object/frameworks/innerkitsimpl/src/communicator/dev_manager.cpp +++ b/data_object/frameworks/innerkitsimpl/src/communicator/dev_manager.cpp @@ -44,24 +44,24 @@ private: void DMStateCallback::OnDeviceOnline(const DmDeviceInfo &deviceInfo) { - std::string udid = softBusAdapter_->GetUdidByNodeId(std::string(deviceInfo.networkId)); - LOG_INFO("[Online] id:%{public}s, name:%{public}s, typeId:%{public}d", SoftBusAdapter::ToBeAnonymous(udid).c_str(), + std::string uuid = DevManager::GetInstance()->GetUuidByNodeId(std::string(deviceInfo.networkId)); + LOG_INFO("[Online] id:%{public}s, name:%{public}s, typeId:%{public}d", SoftBusAdapter::ToBeAnonymous(uuid).c_str(), deviceInfo.deviceName, deviceInfo.deviceTypeId); NotifyAll(deviceInfo, DeviceChangeType::DEVICE_ONLINE); } void DMStateCallback::OnDeviceOffline(const DmDeviceInfo &deviceInfo) { - std::string udid = softBusAdapter_->GetUdidByNodeId(std::string(deviceInfo.networkId)); + std::string uuid = DevManager::GetInstance()->GetUuidByNodeId(std::string(deviceInfo.networkId)); LOG_INFO("[Offline] id:%{public}s, name:%{public}s, typeId:%{public}d", - SoftBusAdapter::ToBeAnonymous(udid).c_str(), deviceInfo.deviceName, deviceInfo.deviceTypeId); + SoftBusAdapter::ToBeAnonymous(uuid).c_str(), deviceInfo.deviceName, deviceInfo.deviceTypeId); NotifyAll(deviceInfo, DeviceChangeType::DEVICE_OFFLINE); } void DMStateCallback::OnDeviceChanged(const DmDeviceInfo &deviceInfo) { - std::string udid = softBusAdapter_->GetUdidByNodeId(std::string(deviceInfo.networkId)); - LOG_INFO("[InfoChange] id:%{public}s, name:%{public}s", SoftBusAdapter::ToBeAnonymous(udid).c_str(), + std::string uuid = DevManager::GetInstance()->GetUuidByNodeId(std::string(deviceInfo.networkId)); + LOG_INFO("[InfoChange] id:%{public}s, name:%{public}s", SoftBusAdapter::ToBeAnonymous(uuid).c_str(), deviceInfo.deviceName); } @@ -136,5 +136,17 @@ void DevManager::RegisterDevCallback() th.detach(); } +std::string DevManager::GetUuidByNodeId(const std::string &nodeId) const +{ + std::string uuid = ""; + int32_t ret = DistributedHardware::DeviceManager::GetInstance().GetEncryptedUuidByNetworkId( + "ohos.objectstore", nodeId.c_str(), uuid); + if (ret != DM_OK) { + LOG_WARN("GetEncryptedUuidByNetworkId error, nodeId:%{public}s", SoftBusAdapter::ToBeAnonymous(nodeId).c_str()); + return ""; + } + return uuid; +} + } // namespace ObjectStore } // namespace OHOS \ No newline at end of file diff --git a/data_object/frameworks/innerkitsimpl/src/communicator/softbus_adapter_standard.cpp b/data_object/frameworks/innerkitsimpl/src/communicator/softbus_adapter_standard.cpp index d72b0f83..dea59211 100644 --- a/data_object/frameworks/innerkitsimpl/src/communicator/softbus_adapter_standard.cpp +++ b/data_object/frameworks/innerkitsimpl/src/communicator/softbus_adapter_standard.cpp @@ -24,6 +24,7 @@ #include "session.h" #include "softbus_adapter.h" #include "softbus_bus_center.h" +#include "dev_manager.h" namespace OHOS { namespace ObjectStore { @@ -38,7 +39,6 @@ constexpr int32_t SOFTBUS_ERR = 1; constexpr int32_t INVALID_SESSION_ID = -1; constexpr int32_t SESSION_NAME_SIZE_MAX = 65; constexpr int32_t DEVICE_ID_SIZE_MAX = 65; -constexpr int32_t ID_BUF_LEN = 65; constexpr size_t TASK_CAPACITY_MAX = 15; using namespace std; @@ -127,15 +127,15 @@ void SoftBusAdapter::NotifyAll(const DeviceInfo &deviceInfo, const DeviceChangeT } } LOG_DEBUG("high"); - std::string udid = GetUdidByNodeId(deviceInfo.deviceId); - LOG_DEBUG("[Notify] to DB from: %{public}s, type:%{public}d", ToBeAnonymous(udid).c_str(), type); + std::string uuid = DevManager::GetInstance()->GetUuidByNodeId(deviceInfo.deviceId); + LOG_DEBUG("[Notify] to DB from: %{public}s, type:%{public}d", ToBeAnonymous(uuid).c_str(), type); UpdateRelationship(deviceInfo.deviceId, type); for (const auto &device : listeners) { if (device == nullptr) { continue; } if (device->GetChangeLevelType() == ChangeLevelType::HIGH) { - DeviceInfo di = { udid, deviceInfo.deviceName, deviceInfo.deviceType }; + DeviceInfo di = { uuid, deviceInfo.deviceName, deviceInfo.deviceType }; device->OnDeviceChanged(di, type); break; } @@ -146,7 +146,7 @@ void SoftBusAdapter::NotifyAll(const DeviceInfo &deviceInfo, const DeviceChangeT continue; } if (device->GetChangeLevelType() == ChangeLevelType::LOW) { - DeviceInfo di = { udid, deviceInfo.deviceName, deviceInfo.deviceType }; + DeviceInfo di = { uuid, deviceInfo.deviceName, deviceInfo.deviceType }; device->OnDeviceChanged(di, DeviceChangeType::DEVICE_OFFLINE); device->OnDeviceChanged(di, type); } @@ -157,7 +157,7 @@ void SoftBusAdapter::NotifyAll(const DeviceInfo &deviceInfo, const DeviceChangeT continue; } if (device->GetChangeLevelType() == ChangeLevelType::MIN) { - DeviceInfo di = { udid, deviceInfo.deviceName, deviceInfo.deviceType }; + DeviceInfo di = { uuid, deviceInfo.deviceName, deviceInfo.deviceType }; device->OnDeviceChanged(di, type); } } @@ -180,8 +180,8 @@ std::vector SoftBusAdapter::GetDeviceList() const LOG_INFO("GetAllNodeDeviceInfo success infoNum=%{public}d", infoNum); for (int i = 0; i < infoNum; i++) { - std::string udid = GetUdidByNodeId(std::string(info[i].networkId)); - DeviceInfo deviceInfo = { udid, std::string(info[i].deviceName), std::to_string(info[i].deviceTypeId) }; + std::string uuid = DevManager::GetInstance()->GetUuidByNodeId(std::string(info[i].networkId)); + DeviceInfo deviceInfo = { uuid, std::string(info[i].deviceName), std::to_string(info[i].deviceTypeId) }; dis.push_back(deviceInfo); } if (info != nullptr) { @@ -202,25 +202,13 @@ DeviceInfo SoftBusAdapter::GetLocalDevice() LOG_ERROR("GetLocalNodeDeviceInfo error"); return DeviceInfo(); } - std::string uuid = GetUdidByNodeId(std::string(info.networkId)); + std::string uuid = DevManager::GetInstance()->GetUuidByNodeId(std::string(info.networkId)); LOG_DEBUG("[LocalDevice] id:%{private}s, name:%{private}s, type:%{private}d", ToBeAnonymous(uuid).c_str(), info.deviceName, info.deviceTypeId); localInfo_ = { uuid, std::string(info.deviceName), std::to_string(info.deviceTypeId) }; return localInfo_; } -std::string SoftBusAdapter::GetUdidByNodeId(const std::string &nodeId) const -{ - char udid[ID_BUF_LEN] = { 0 }; - int32_t ret = GetNodeKeyInfo("ohos.objectstore", nodeId.c_str(), NodeDeviceInfoKey::NODE_KEY_UDID, - reinterpret_cast(udid), ID_BUF_LEN); - if (ret != SOFTBUS_OK) { - LOG_WARN("GetNodeKeyInfo error, nodeId:%{public}s", ToBeAnonymous(nodeId).c_str()); - return ""; - } - return std::string(udid); -} - DeviceInfo SoftBusAdapter::GetLocalBasicInfo() const { LOG_DEBUG("begin"); @@ -265,19 +253,19 @@ std::vector SoftBusAdapter::GetRemoteNodesBasicInfo() const void SoftBusAdapter::UpdateRelationship(const std::string &networkid, const DeviceChangeType &type) { - auto udid = GetUdidByNodeId(networkid); + auto uuid = DevManager::GetInstance()->GetUuidByNodeId(networkid); lock_guard lock(networkMutex_); switch (type) { case DeviceChangeType::DEVICE_OFFLINE: { - auto size = this->networkId2Udid_.erase(networkid); + auto size = this->networkId2Uuid_.erase(networkid); if (size == 0) { LOG_WARN("not found id:%{public}s.", networkid.c_str()); } break; } case DeviceChangeType::DEVICE_ONLINE: { - std::pair value = { networkid, udid }; - auto res = this->networkId2Udid_.insert(std::move(value)); + std::pair value = { networkid, uuid }; + auto res = this->networkId2Uuid_.insert(std::move(value)); if (!res.second) { LOG_WARN("insert failed."); } @@ -293,8 +281,8 @@ std::string SoftBusAdapter::ToNodeID(const std::string &nodeId) const { { lock_guard lock(networkMutex_); - for (auto const &e : networkId2Udid_) { - if (nodeId == e.second) { // id is udid + for (auto const &e : networkId2Uuid_) { + if (nodeId == e.second) { // id is uuid return e.first; } } @@ -309,12 +297,12 @@ std::string SoftBusAdapter::ToNodeID(const std::string &nodeId) const if (ret == SOFTBUS_OK) { lock_guard lock(networkMutex_); for (int i = 0; i < infoNum; i++) { - if (networkId2Udid_.find(info[i].networkId) != networkId2Udid_.end()) { + if (networkId2Uuid_.find(info[i].networkId) != networkId2Uuid_.end()) { continue; } - auto udid = GetUdidByNodeId(std::string(info[i].networkId)); - networkId2Udid_.insert({ info[i].networkId, udid }); - if (udid == nodeId) { + auto uuid = DevManager::GetInstance()->GetUuidByNodeId(std::string(info[i].networkId)); + networkId2Uuid_.insert({ info[i].networkId, uuid }); + if (uuid == nodeId) { networkId = info[i].networkId; } } @@ -588,15 +576,15 @@ int AppDataListenerWrap::OnSessionOpened(int sessionId, int result) LOG_WARN("get my peer device id failed, session id is %{public}d.", sessionId); return SOFTBUS_ERR; } - std::string peerUdid = softBusAdapter_->GetUdidByNodeId(std::string(peerDevId)); + std::string peerUuid = DevManager::GetInstance()->GetUuidByNodeId(std::string(peerDevId)); LOG_DEBUG("[SessionOpen] mySessionName:%{public}s, " "peerSessionName:%{public}s, peerDevId:%{public}s", - mySessionName, peerSessionName, SoftBusAdapter::ToBeAnonymous(peerUdid).c_str()); + mySessionName, peerSessionName, SoftBusAdapter::ToBeAnonymous(peerUuid).c_str()); if (strlen(peerSessionName) < 1) { - softBusAdapter_->InsertSession(std::string(mySessionName) + peerUdid); + softBusAdapter_->InsertSession(std::string(mySessionName) + peerUuid); } else { - softBusAdapter_->InsertSession(std::string(peerSessionName) + peerUdid); + softBusAdapter_->InsertSession(std::string(peerSessionName) + peerUuid); } return 0; } @@ -624,15 +612,15 @@ void AppDataListenerWrap::OnSessionClosed(int sessionId) LOG_WARN("get my peer device id failed, session id is %{public}d.", sessionId); return; } - std::string peerUdid = softBusAdapter_->GetUdidByNodeId(std::string(peerDevId)); + std::string peerUuid = DevManager::GetInstance()->GetUuidByNodeId(std::string(peerDevId)); LOG_DEBUG("[SessionClosed] mySessionName:%{public}s, " "peerSessionName:%{public}s, peerDevId:%{public}s", - mySessionName, peerSessionName, SoftBusAdapter::ToBeAnonymous(peerUdid).c_str()); + mySessionName, peerSessionName, SoftBusAdapter::ToBeAnonymous(peerUuid).c_str()); if (strlen(peerSessionName) < 1) { - softBusAdapter_->DeleteSession(std::string(mySessionName) + peerUdid); + softBusAdapter_->DeleteSession(std::string(mySessionName) + peerUuid); } else { - softBusAdapter_->DeleteSession(std::string(peerSessionName) + peerUdid); + softBusAdapter_->DeleteSession(std::string(peerSessionName) + peerUuid); } } @@ -654,11 +642,11 @@ void AppDataListenerWrap::OnMessageReceived(int sessionId, const void *data, uns LOG_WARN("get my peer device id failed, session id is %{public}d.", sessionId); return; } - std::string peerUdid = softBusAdapter_->GetUdidByNodeId(std::string(peerDevId)); + std::string peerUuid = DevManager::GetInstance()->GetUuidByNodeId(std::string(peerDevId)); LOG_DEBUG("[MessageReceived] session id:%{public}d, " "peerSessionName:%{public}s, peerDevId:%{public}s", - sessionId, peerSessionName, SoftBusAdapter::ToBeAnonymous(peerUdid).c_str()); - NotifyDataListeners(reinterpret_cast(data), dataLen, peerUdid, { std::string(peerSessionName) }); + sessionId, peerSessionName, SoftBusAdapter::ToBeAnonymous(peerUuid).c_str()); + NotifyDataListeners(reinterpret_cast(data), dataLen, peerUuid, { std::string(peerSessionName) }); } void AppDataListenerWrap::OnBytesReceived(int sessionId, const void *data, unsigned int dataLen) @@ -679,11 +667,11 @@ void AppDataListenerWrap::OnBytesReceived(int sessionId, const void *data, unsig LOG_WARN("get my peer device id failed, session id is %{public}d.", sessionId); return; } - std::string peerUdid = softBusAdapter_->GetUdidByNodeId(std::string(peerDevId)); + std::string peerUuid = DevManager::GetInstance()->GetUuidByNodeId(std::string(peerDevId)); LOG_DEBUG("[BytesReceived] session id:%{public}d, peerSessionName:%{public}s, " "peerDevId:%{public}s", - sessionId, peerSessionName, SoftBusAdapter::ToBeAnonymous(peerUdid).c_str()); - NotifyDataListeners(reinterpret_cast(data), dataLen, peerUdid, { std::string(peerSessionName) }); + sessionId, peerSessionName, SoftBusAdapter::ToBeAnonymous(peerUuid).c_str()); + NotifyDataListeners(reinterpret_cast(data), dataLen, peerUuid, { std::string(peerSessionName) }); } void AppDataListenerWrap::NotifyDataListeners( diff --git a/data_object/frameworks/innerkitsimpl/test/unittest/src/communicator_test.cpp b/data_object/frameworks/innerkitsimpl/test/unittest/src/communicator_test.cpp index 15249e70..8d6d3adb 100644 --- a/data_object/frameworks/innerkitsimpl/test/unittest/src/communicator_test.cpp +++ b/data_object/frameworks/innerkitsimpl/test/unittest/src/communicator_test.cpp @@ -26,6 +26,7 @@ #include "token_setproc.h" #include "app_types.h" #include "softbus_adapter.h" +#include "dev_manager.h" #include "app_device_status_change_listener.h" #include "app_data_change_listener.h" #include "mock_app_device_change_listener.h" @@ -456,16 +457,14 @@ HWTEST_F(NativeCommunicatorTest, SoftBusAdapter_GetLocalDevice_001, TestSize.Lev /** - * @tc.name: SoftBusAdapter_GetUdidByNodeId_001 - * @tc.desc: test SoftBusAdapter GetUdidByNodeId. + * @tc.name: DevManager_GetUuidByNodeId_001 + * @tc.desc: test DevManager GetUuidByNodeId. * @tc.type: FUNC */ -HWTEST_F(NativeCommunicatorTest, SoftBusAdapter_GetUdidByNodeId_001, TestSize.Level1) +HWTEST_F(NativeCommunicatorTest, DevManager_GetUuidByNodeId_001, TestSize.Level1) { std::string nodeId = "nodeId01"; - SoftBusAdapter *softBusAdapter = new SoftBusAdapter(); - auto ret = softBusAdapter->GetUdidByNodeId(nodeId); + auto ret = DevManager::GetInstance()->GetUuidByNodeId(nodeId); EXPECT_EQ(true, ret.empty()); - delete softBusAdapter; } } \ No newline at end of file diff --git a/data_object/frameworks/innerkitsimpl/test/unittest/src/object_store_test.cpp b/data_object/frameworks/innerkitsimpl/test/unittest/src/object_store_test.cpp index 4effc12b..2a7ca405 100644 --- a/data_object/frameworks/innerkitsimpl/test/unittest/src/object_store_test.cpp +++ b/data_object/frameworks/innerkitsimpl/test/unittest/src/object_store_test.cpp @@ -64,39 +64,6 @@ void StatusNotifierImpl::OnChanged(const std::string &sessionId, const std::string &onlineStatus) { } -static void TestSetSessionId(std::string bundleName, std::string sessionId) -{ - DistributedObjectStore *objectStore = DistributedObjectStore::GetInstance(bundleName); - EXPECT_NE(nullptr, objectStore); - DistributedObject *object = objectStore->CreateObject(sessionId); - EXPECT_NE(nullptr, object); - - uint32_t ret = objectStore->DeleteObject(sessionId); - EXPECT_EQ(SUCCESS, ret); -} - -static void TestSaveAndRevokeSave(std::string bundleName, std::string sessionId) -{ - DistributedObjectStore *objectStore = DistributedObjectStore::GetInstance(bundleName); - EXPECT_NE(nullptr, objectStore); - DistributedObject *object = objectStore->CreateObject(sessionId); - EXPECT_NE(nullptr, object); - - uint32_t ret = object->PutString("name", "zhangsan"); - EXPECT_EQ(SUCCESS, ret); - ret = object->PutDouble("salary", SALARY); - EXPECT_EQ(SUCCESS, ret); - ret = object->PutBoolean("isTrue", true); - EXPECT_EQ(SUCCESS, ret); - - ret = object->Save("local"); - EXPECT_EQ(SUCCESS, ret); - ret = object->RevokeSave(); - EXPECT_EQ(SUCCESS, ret); - - ret = objectStore->DeleteObject(sessionId); - EXPECT_EQ(SUCCESS, ret); -} void GrantPermissionNative() { @@ -400,9 +367,18 @@ HWTEST_F(NativeObjectStoreTest, DistributedObject_GetSessionId_001, TestSize.Lev */ HWTEST_F(NativeObjectStoreTest, DistributedObject_TestSetSessionId_001, TestSize.Level1) { - std::thread t1(TestSetSessionId, "default1", "session1"); - std::thread t2(TestSetSessionId, "default2", "session2"); - std::thread t3(TestSetSessionId, "default3", "session3"); + auto testSetSessionId = [] (std::string bundleName, std::string sessionId) { + DistributedObjectStore *objectStore = DistributedObjectStore::GetInstance(bundleName); + EXPECT_NE(nullptr, objectStore); + DistributedObject *object = objectStore->CreateObject(sessionId); + EXPECT_NE(nullptr, object); + + uint32_t ret = objectStore->DeleteObject(sessionId); + EXPECT_EQ(SUCCESS, ret); + }; + std::thread t1(testSetSessionId, "default1", "session1"); + std::thread t2(testSetSessionId, "default2", "session2"); + std::thread t3(testSetSessionId, "default3", "session3"); t1.join(); t2.join(); t3.join(); @@ -454,7 +430,25 @@ HWTEST_F(NativeObjectStoreTest, DistributedObject_Save_RevokeSave_001, TestSize. { std::string bundleName = "default"; std::string sessionId = "123456"; - TestSaveAndRevokeSave(bundleName, sessionId); + DistributedObjectStore *objectStore = DistributedObjectStore::GetInstance(bundleName); + EXPECT_NE(nullptr, objectStore); + DistributedObject *object = objectStore->CreateObject(sessionId); + EXPECT_NE(nullptr, object); + + uint32_t ret = object->PutString("name", "zhangsan"); + EXPECT_EQ(SUCCESS, ret); + ret = object->PutDouble("salary", SALARY); + EXPECT_EQ(SUCCESS, ret); + ret = object->PutBoolean("isTrue", true); + EXPECT_EQ(SUCCESS, ret); + + ret = object->Save("local"); + EXPECT_EQ(SUCCESS, ret); + ret = object->RevokeSave(); + EXPECT_EQ(SUCCESS, ret); + + ret = objectStore->DeleteObject(sessionId); + EXPECT_EQ(SUCCESS, ret); } /** @@ -464,9 +458,30 @@ HWTEST_F(NativeObjectStoreTest, DistributedObject_Save_RevokeSave_001, TestSize. */ HWTEST_F(NativeObjectStoreTest, DistributedObject_Save_RevokeSave_002, TestSize.Level1) { - std::thread t1(TestSaveAndRevokeSave, "default1", "session1"); - std::thread t2(TestSaveAndRevokeSave, "default2", "session2"); - std::thread t3(TestSaveAndRevokeSave, "default3", "session3"); + auto testSaveAndRevokeSave = [](std::string bundleName, std::string sessionId) { + DistributedObjectStore *objectStore = DistributedObjectStore::GetInstance(bundleName); + EXPECT_NE(nullptr, objectStore); + DistributedObject *object = objectStore->CreateObject(sessionId); + EXPECT_NE(nullptr, object); + + uint32_t ret = object->PutString("name", "zhangsan"); + EXPECT_EQ(SUCCESS, ret); + ret = object->PutDouble("salary", SALARY); + EXPECT_EQ(SUCCESS, ret); + ret = object->PutBoolean("isTrue", true); + EXPECT_EQ(SUCCESS, ret); + + ret = object->Save("local"); + EXPECT_EQ(SUCCESS, ret); + ret = object->RevokeSave(); + EXPECT_EQ(SUCCESS, ret); + + ret = objectStore->DeleteObject(sessionId); + EXPECT_EQ(SUCCESS, ret); + }; + std::thread t1(testSaveAndRevokeSave, "default1", "session1"); + std::thread t2(testSaveAndRevokeSave, "default2", "session2"); + std::thread t3(testSaveAndRevokeSave, "default3", "session3"); t1.join(); t2.join(); t3.join(); diff --git a/data_object/frameworks/jskitsimpl/include/adaptor/js_common.h b/data_object/frameworks/jskitsimpl/include/adaptor/js_common.h index 33b8cf7c..dddd4732 100644 --- a/data_object/frameworks/jskitsimpl/include/adaptor/js_common.h +++ b/data_object/frameworks/jskitsimpl/include/adaptor/js_common.h @@ -24,6 +24,7 @@ namespace OHOS::ObjectStore { return nullptr; \ } \ } + #define CHECK_EQUAL_WITH_RETURN_VOID(status, value) \ { \ if (status != value) { \ @@ -31,6 +32,7 @@ namespace OHOS::ObjectStore { return; \ } \ } + #define CHECK_EQUAL_WITH_RETURN_FALSE(status, value) \ { \ if (status != value) { \ @@ -38,6 +40,7 @@ namespace OHOS::ObjectStore { return false; \ } \ } + #define ASSERT_MATCH_ELSE_RETURN_VOID(condition) \ { \ if (!(condition)) { \ @@ -45,6 +48,7 @@ namespace OHOS::ObjectStore { return; \ } \ } + #define ASSERT_MATCH_ELSE_RETURN_NULL(condition) \ { \ if (!(condition)) { \ @@ -52,6 +56,7 @@ namespace OHOS::ObjectStore { return nullptr; \ } \ } + #define ASSERT_MATCH_ELSE_GOTO_ERROR(condition) \ { \ if (!(condition)) { \ @@ -59,6 +64,27 @@ namespace OHOS::ObjectStore { goto ERROR; \ } \ } + +#define CHECK_API_VALID_ELSE_RETURN_VOID(assertion) \ + do { \ + if (!(assertion)) { \ + std::shared_ptr apiError = std::make_shared(); \ + ctxt->SetError(apiError); \ + ctxt->status = napi_generic_failure; \ + return; \ + } \ + } while (0) + +#define CHECK_VALID_ELSE_RETURN_VOID(assertion, msg) \ + do { \ + if (!(assertion)) { \ + std::shared_ptr innerError = std::make_shared(); \ + ctxt->SetError(innerError); \ + ctxt->status = napi_generic_failure; \ + ctxt->message = msg; \ + return; \ + } \ + } while (0) } // namespace OHOS::ObjectStore static const char *CHANGE = "change"; static const char *STATUS = "status"; diff --git a/data_object/frameworks/jskitsimpl/include/common/object_error.h b/data_object/frameworks/jskitsimpl/include/common/object_error.h index a982e9bc..8ebe82e4 100644 --- a/data_object/frameworks/jskitsimpl/include/common/object_error.h +++ b/data_object/frameworks/jskitsimpl/include/common/object_error.h @@ -20,6 +20,7 @@ namespace OHOS { namespace ObjectStore { +static const int EXCEPTION_DEVICE_NOT_SUPPORT = 801; static const int EXCEPTION_PARAMETER_CHECK = 401; static const int EXCEPTION_NO_PERMISSION = 201; static const int EXCEPTION_DB_EXIST = 15400001; @@ -73,6 +74,13 @@ public: std::string GetMessage() override; int GetCode() override; }; + +class DeviceNotSupportedError : public Error { +public: + DeviceNotSupportedError() = default; + std::string GetMessage() override; + int GetCode() override; +}; } // namespace ObjectStore } // namespace OHOS diff --git a/data_object/frameworks/jskitsimpl/src/adaptor/js_distributedobject.cpp b/data_object/frameworks/jskitsimpl/src/adaptor/js_distributedobject.cpp index 5800f164..d6686780 100644 --- a/data_object/frameworks/jskitsimpl/src/adaptor/js_distributedobject.cpp +++ b/data_object/frameworks/jskitsimpl/src/adaptor/js_distributedobject.cpp @@ -248,6 +248,16 @@ napi_value JSDistributedObject::JSSave(napi_env env, napi_callback_info info) }; ctxt->GetCbInfo(env, info, getCbOpe); CHECH_STATUS_ERRCODE(env, ctxt->status != napi_invalid_arg, ctxt->error); + auto execute = [ctxt]() { + LOG_INFO("start"); + CHECH_STATUS_RETURN_VOID(env, ctxt->wrapper != nullptr, ctxt, "wrapper is null"); + CHECH_STATUS_RETURN_VOID(env, ctxt->wrapper->GetObject() != nullptr, ctxt, "object is null"); + uint32_t status = ctxt->wrapper->GetObject()->Save(ctxt->deviceId); + CHECK_API_VALID_ELSE_RETURN_VOID(status != ERR_PROCESSING); + CHECK_VALID_ELSE_RETURN_VOID(status == SUCCESS, "operation failed"); + ctxt->status = napi_ok; + LOG_INFO("end"); + }; auto output = [env, ctxt](napi_value &result) { if (ctxt->status == napi_ok) { CHECH_STATUS_RETURN_VOID(env, ctxt->wrapper != nullptr, ctxt, "wrapper is null"); @@ -258,22 +268,6 @@ napi_value JSDistributedObject::JSSave(napi_env env, napi_callback_info info) CHECK_STATUS_RETURN_VOID(ctxt, "output failed!"); } }; - auto execute = [ctxt]() { - LOG_INFO("start"); - CHECH_STATUS_RETURN_VOID(env, ctxt->wrapper != nullptr, ctxt, "wrapper is null"); - CHECH_STATUS_RETURN_VOID(env, ctxt->wrapper->GetObject() != nullptr, ctxt, "object is null"); - uint32_t status = ctxt->wrapper->GetObject()->Save(ctxt->deviceId); - if (status != SUCCESS) { - LOG_ERROR("Save failed, status = %{public}d", status); - auto innerError = std::make_shared(); - ctxt->SetError(innerError); - ctxt->status = napi_generic_failure; - ctxt->message = std::string("operation failed"); - return; - } - ctxt->status = napi_ok; - LOG_INFO("end"); - }; return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute, output); } @@ -300,7 +294,15 @@ napi_value JSDistributedObject::JSRevokeSave(napi_env env, napi_callback_info in napi_throw_error((env), std::to_string(ctxt->error->GetCode()).c_str(), ctxt->error->GetMessage().c_str()); return nullptr; } - + auto execute = [ctxt]() { + CHECH_STATUS_RETURN_VOID(env, ctxt->wrapper != nullptr, ctxt, "wrapper is null"); + CHECH_STATUS_RETURN_VOID(env, ctxt->wrapper->GetObject() != nullptr, ctxt, "object is null"); + uint32_t status = ctxt->wrapper->GetObject()->RevokeSave(); + CHECK_API_VALID_ELSE_RETURN_VOID(status != ERR_PROCESSING); + CHECK_VALID_ELSE_RETURN_VOID(status == SUCCESS, "operation failed"); + ctxt->status = napi_ok; + LOG_INFO("end"); + }; auto output = [env, ctxt](napi_value &result) { if (ctxt->status == napi_ok) { CHECH_STATUS_RETURN_VOID(env, ctxt->wrapper != nullptr, ctxt, "wrapper is null"); @@ -311,25 +313,7 @@ napi_value JSDistributedObject::JSRevokeSave(napi_env env, napi_callback_info in CHECK_STATUS_RETURN_VOID(ctxt, "output failed!"); } }; - return NapiQueue::AsyncWork( - env, ctxt, std::string(__FUNCTION__), - [ctxt]() { - LOG_INFO("start"); - CHECH_STATUS_RETURN_VOID(env, ctxt->wrapper != nullptr, ctxt, "wrapper is null"); - CHECH_STATUS_RETURN_VOID(env, ctxt->wrapper->GetObject() != nullptr, ctxt, "object is null"); - uint32_t status = ctxt->wrapper->GetObject()->RevokeSave(); - if (status != SUCCESS) { - LOG_ERROR("Save failed, status = %{public}d", status); - auto innerError = std::make_shared(); - ctxt->SetError(innerError); - ctxt->status = napi_generic_failure; - ctxt->message = std::string("operation failed"); - return; - } - ctxt->status = napi_ok; - LOG_INFO("end"); - }, - output); + return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute, output); } napi_value JSDistributedObject::GetSaveResultCons( diff --git a/data_object/frameworks/jskitsimpl/src/adaptor/js_distributedobjectstore.cpp b/data_object/frameworks/jskitsimpl/src/adaptor/js_distributedobjectstore.cpp index e8c92e82..2ff20210 100644 --- a/data_object/frameworks/jskitsimpl/src/adaptor/js_distributedobjectstore.cpp +++ b/data_object/frameworks/jskitsimpl/src/adaptor/js_distributedobjectstore.cpp @@ -108,7 +108,11 @@ napi_value JSDistributedObjectStore::NewDistributedObject( napi_value result; napi_status status = napi_new_instance(env, JSDistributedObject::GetCons(env), 0, nullptr, &result); CHECK_EQUAL_WITH_RETURN_NULL(status, napi_ok); - JSObjectWrapper *objectWrapper = new JSObjectWrapper(objectStore, object); + JSObjectWrapper *objectWrapper = new (std::nothrow) JSObjectWrapper(objectStore, object); + if (objectWrapper == nullptr) { + LOG_ERROR("JSDistributedObjectStore::NewDistributedObject no memory for objectWrapper malloc!"); + return nullptr; + } objectWrapper->SetObjectId(objectId); status = napi_wrap( env, result, objectWrapper, diff --git a/data_object/frameworks/jskitsimpl/src/adaptor/js_watcher.cpp b/data_object/frameworks/jskitsimpl/src/adaptor/js_watcher.cpp index 40f96472..9e1895d0 100644 --- a/data_object/frameworks/jskitsimpl/src/adaptor/js_watcher.cpp +++ b/data_object/frameworks/jskitsimpl/src/adaptor/js_watcher.cpp @@ -105,7 +105,11 @@ void JSWatcher::Emit(const char *type, const std::string &sessionId, const std:: } for (EventHandler *handler = listener->handlers_; handler != nullptr; handler = handler->next) { - ChangeArgs *changeArgs = new ChangeArgs(handler->callbackRef, sessionId, changeData); + ChangeArgs *changeArgs = new (std::nothrow) ChangeArgs(handler->callbackRef, sessionId, changeData); + if (changeArgs == nullptr) { + LOG_ERROR("JSWatcher::Emit no memory for changeArgs malloc!"); + return; + } CallFunction(ProcessChange, changeArgs); } } @@ -171,7 +175,11 @@ void JSWatcher::Emit( } for (EventHandler *handler = listener->handlers_; handler != nullptr; handler = handler->next) { - StatusArgs *changeArgs = new StatusArgs(handler->callbackRef, sessionId, networkId, status); + StatusArgs *changeArgs = new (std::nothrow) StatusArgs(handler->callbackRef, sessionId, networkId, status); + if (changeArgs == nullptr) { + LOG_ERROR("JSWatcher::Emit no memory for StatusArgs malloc!"); + return; + } CallFunction(ProcessStatus, changeArgs); } return; @@ -248,10 +256,18 @@ bool EventListener::Add(napi_env env, napi_value handler) } if (handlers_ == nullptr) { - handlers_ = new EventHandler(); + handlers_ = new (std::nothrow) EventHandler(); + if (handlers_ == nullptr) { + LOG_ERROR("EventListener::Add no memory for EventHandler malloc!"); + return false; + } handlers_->next = nullptr; } else { - auto temp = new EventHandler(); + auto temp = new (std::nothrow) EventHandler(); + if (temp == nullptr) { + LOG_ERROR("EventListener::Add no memory for EventHandler malloc!"); + return false; + } temp->next = handlers_; handlers_ = temp; } diff --git a/data_object/frameworks/jskitsimpl/src/common/object_error.cpp b/data_object/frameworks/jskitsimpl/src/common/object_error.cpp index 0f03e14b..12347fd0 100644 --- a/data_object/frameworks/jskitsimpl/src/common/object_error.cpp +++ b/data_object/frameworks/jskitsimpl/src/common/object_error.cpp @@ -67,5 +67,15 @@ int InnerError::GetCode() { return EXCEPTION_INNER; } + +std::string DeviceNotSupportedError::GetMessage() +{ + return "Capability not supported."; +} + +int DeviceNotSupportedError::GetCode() +{ + return EXCEPTION_DEVICE_NOT_SUPPORT; +} } // namespace ObjectStore } // namespace OHOS \ No newline at end of file diff --git a/data_object/frameworks/jskitsimpl/test/unittest/src/ObjectStoreJsunit.test.js b/data_object/frameworks/jskitsimpl/test/unittest/src/ObjectStoreJsunit.test.js index 380d8808..aed6d72f 100644 --- a/data_object/frameworks/jskitsimpl/test/unittest/src/ObjectStoreJsunit.test.js +++ b/data_object/frameworks/jskitsimpl/test/unittest/src/ObjectStoreJsunit.test.js @@ -63,6 +63,7 @@ function statusCallback4(sessionId, networkId, status) { const TIMEOUT = 1500; const PERMISSION_USER_SET = 1; const PERMISSION_USER_NAME = "ohos.permission.DISTRIBUTED_DATASYNC"; +const CATCH_ERR = -1; var tokenID = undefined; async function grantPerm() { console.info("====grant Permission start===="); @@ -677,33 +678,74 @@ describe('objectStoreTest',function () { * @tc.name: testSave001 * @tc.desc: test save local * @tc.type: FUNC - * @tc.require: I4WDAK + * @tc.require: */ - it('testSave001', 0, async function () { + it('testSave001', 0, async function (done) { console.log(TAG + "************* testSave001 start *************"); var g_object = distributedObject.createDistributedObject({ name: "Amy", age: 18, isVis: false }); expect(g_object == undefined).assertEqual(false); - g_object.setSessionId("tmpsession1"); - expect("tmpsession1" == g_object.__sessionId).assertEqual(true); - - let result = await g_object.save("local"); - expect(result.sessionId == "tmpsession1").assertEqual(true); - expect(result.version == g_object.__version).assertEqual(true); - expect(result.deviceId == "local").assertEqual(true); + g_object.setSessionId("testSession001"); + expect("testSession001" == g_object.__sessionId).assertEqual(true); + + g_object.save("local").then((ret) => { + expect(ret.sessionId == "testSession001").assertEqual(true); + expect(ret.version == g_object.__version).assertEqual(true); + expect(ret.deviceId == "local").assertEqual(true); + done(); + + g_object.setSessionId(""); + g_object.name = undefined; + g_object.age = undefined; + g_object.isVis = undefined; + g_object.setSessionId("testSession001"); + + expect(g_object.name == "Amy").assertEqual(true); + expect(g_object.age == 18).assertEqual(true); + expect(g_object.isVis == false).assertEqual(true); + }).catch((err) => { + expect("801").assertEqual(err.code.toString()); + done(); + }); + console.log(TAG + "************* testSave001 end *************"); + }) - g_object.setSessionId(""); - g_object.name = undefined; - g_object.age = undefined; - g_object.isVis = undefined; - g_object.setSessionId("tmpsession1"); + /** + * @tc.name: testSave002 + * @tc.desc: test save local + * @tc.type: FUNC + * @tc.require: + */ + it('testSave002', 0, async function (done) { + console.log(TAG + "************* testSave002 start *************"); + var g_object = distributedObject.createDistributedObject({ name: "Amy", age: 18, isVis: false }); + expect(g_object == undefined).assertEqual(false); - expect(g_object.name == "Amy").assertEqual(true); - expect(g_object.age == 18).assertEqual(true); - expect(g_object.isVis == false).assertEqual(true); - console.log(TAG + "************* testSave001 end *************"); - g_object.setSessionId(""); + g_object.setSessionId("testSession002"); + expect("testSession002" == g_object.__sessionId).assertEqual(true); + g_object.save("local", (err, result) => { + if (err) { + expect("801").assertEqual(err.code.toString()); + done(); + return; + } + expect(result.sessionId == "testSession002").assertEqual(true); + expect(result.version == g_object.__version).assertEqual(true); + expect(result.deviceId == "local").assertEqual(true); + done(); + + g_object.setSessionId(""); + g_object.name = undefined; + g_object.age = undefined; + g_object.isVis = undefined; + g_object.setSessionId("testSession002"); + + expect(g_object.name == "Amy").assertEqual(true); + expect(g_object.age == 18).assertEqual(true); + expect(g_object.isVis == false).assertEqual(true); + }) + console.log(TAG + "************* testSave002 end *************"); }) /** @@ -712,36 +754,92 @@ describe('objectStoreTest',function () { * @tc.type: FUNC * @tc.require: I4WDAK */ - it('testRevokeSave001', 0, async function () { + it('testRevokeSave001', 0, async function (done) { console.log(TAG + "************* testRevokeSave001 start *************"); var g_object = distributedObject.createDistributedObject({ name: "Amy", age: 18, isVis: false }); expect(g_object == undefined).assertEqual(false); - g_object.setSessionId("123456"); - expect("123456" == g_object.__sessionId).assertEqual(true); + g_object.setSessionId("testSession003"); + expect("testSession003" == g_object.__sessionId).assertEqual(true); - let result = await g_object.save("local"); - expect(result.sessionId == "123456").assertEqual(true); - expect(result.version == g_object.__version).assertEqual(true); - expect(result.deviceId == "local").assertEqual(true); + g_object.save("local", (err, result) => { + if (err) { + expect("801").assertEqual(err.code.toString()); + done(); + return; + } + expect(result.sessionId == "testSession003").assertEqual(true); + expect(result.version == g_object.__version).assertEqual(true); + expect(result.deviceId == "local").assertEqual(true); + g_object.revokeSave((err, result) => { + if (err) { + expect("801").assertEqual(err.code.toString()); + done(); + return; + } + expect("testSession003" == result.sessionId).assertEqual(true); + g_object.setSessionId(""); + g_object.name = undefined; + g_object.age = undefined; + g_object.isVis = undefined; + g_object.setSessionId("testSession003"); + + expect(g_object.name == undefined).assertEqual(true); + expect(g_object.age == undefined).assertEqual(true); + expect(g_object.isVis == undefined).assertEqual(true); + done(); + }) + }); - result = await g_object.revokeSave(); + console.log(TAG + "************* testRevokeSave001 end *************"); + }) + /** + * @tc.name: testRevokeSave002 + * @tc.desc: test save local + * @tc.type: FUNC + * @tc.require: + */ + it('testRevokeSave002', 0, async function () { + console.log(TAG + "************* testRevokeSave002 start *************"); + var g_object = distributedObject.createDistributedObject({ name: "Amy", age: 18, isVis: false }); + expect(g_object == undefined).assertEqual(false); + + g_object.setSessionId("testSession004"); + expect("testSession004" == g_object.__sessionId).assertEqual(true); + + let result = await g_object.save("local").catch((err)=> { + expect("801").assertEqual(err.code.toString()); + return CATCH_ERR; + }); + if (result === CATCH_ERR) { + return; + } + + expect(result.sessionId.toString() == "testSession004").assertEqual(true); + expect(result.version.toString() == g_object.__version.toString()).assertEqual(true); + expect(result.deviceId.toString() == "local").assertEqual(true); + + result = await g_object.revokeSave().catch((err)=> { + expect("801").assertEqual(err.code.toString()); + return CATCH_ERR; + }); + + if (result === CATCH_ERR) { + return; + } g_object.setSessionId(""); g_object.name = undefined; g_object.age = undefined; g_object.isVis = undefined; - g_object.setSessionId("123456"); + g_object.setSessionId("testSession004"); expect(g_object.name == undefined).assertEqual(true); expect(g_object.age == undefined).assertEqual(true); expect(g_object.isVis == undefined).assertEqual(true); - expect(result.sessionId == "123456").assertEqual(true); - - console.log(TAG + "************* testRevokeSave001 end *************"); - g_object.setSessionId(""); + console.log(TAG + "************* testRevokeSave002 end *************"); }) /** @@ -752,25 +850,21 @@ describe('objectStoreTest',function () { */ it('OnstatusRestored001', 0, async function () { console.log(TAG + "************* OnstatusRestored001 start *************"); - var g_object = distributedObject.createDistributedObject({ name: undefined, age: undefined, isVis: undefined }); - g_object.setSessionId("123456"); - g_object.name = "jack"; - g_object.age = 19; - g_object.isVis = true; - - let result = await g_object.save("local"); - expect(result.sessionId == "123456").assertEqual(true); + var g_object = distributedObject.createDistributedObject({ name: "Amy", age: 18, isVis: false }); + g_object.on("status", statusCallback4); + g_object.setSessionId("testSession005"); + let result = await g_object.save("local").catch((err)=> { + expect("801").assertEqual(err.code.toString()); + return CATCH_ERR; + }); + if (result === CATCH_ERR) { + return; + } + expect(result.sessionId == "testSession005").assertEqual(true); expect(result.version == g_object.__version).assertEqual(true); expect(result.deviceId == "local").assertEqual(true); - g_object.setSessionId(""); - - g_object.on("status", statusCallback4); - - g_object.setSessionId("123456"); - g_object.setSessionId(""); console.log(TAG + "************* OnstatusRestored001 end *************"); - }) console.log(TAG + "*************Unit Test End*************"); diff --git a/data_object/frameworks/jskitsimpl/test/unittest/src/ObjectStoreJsunitV9.test.js b/data_object/frameworks/jskitsimpl/test/unittest/src/ObjectStoreJsunitV9.test.js index c1e3d4b8..02b69e9b 100644 --- a/data_object/frameworks/jskitsimpl/test/unittest/src/ObjectStoreJsunitV9.test.js +++ b/data_object/frameworks/jskitsimpl/test/unittest/src/ObjectStoreJsunitV9.test.js @@ -42,6 +42,7 @@ function statusCallback2(sessionId, networkId, status) { const PERMISSION_USER_SET = 1; const PERMISSION_USER_NAME = "ohos.permission.DISTRIBUTED_DATASYNC"; +const CATCH_ERR = -1; var tokenID = undefined; async function grantPerm() { console.info("====grant Permission start===="); @@ -373,7 +374,7 @@ describe('objectStoreTest', function () { }) /** - * @tc.name:V9testOff002 + * @tc.name: V9testOff002 * @tc.desc object join session and off,object can not receive callback * @tc.type: FUNC */ @@ -458,44 +459,38 @@ describe('objectStoreTest', function () { * @tc.desc: test save local * @tc.type: FUNC */ - it('V9testSave001', 0, async function () { + it('V9testSave001', 0, async function (done) { console.log(TAG + "************* V9testSave001 start *************"); var g_object = distributedObject.create(context, {name: "Amy", age: 18, isVis: false}); expect(g_object == undefined).assertEqual(false); - g_object.setSessionId("tmpsession1").then(() => { + g_object.setSessionId("mySession1").then(() => { console.info("join session"); }).catch((error) => { console.info(TAG + error.code + error.message); }); - expect("tmpsession1" == g_object.__sessionId).assertEqual(true); + expect("mySession1" == g_object.__sessionId).assertEqual(true); - let result = await g_object.save("local"); - expect(result.sessionId == "tmpsession1").assertEqual(true); - expect(result.version == g_object.__version).assertEqual(true); - expect(result.deviceId == "local").assertEqual(true); + g_object.save("local").then((ret) => { + expect(ret.sessionId == "mySession1").assertEqual(true); + expect(ret.version == g_object.__version).assertEqual(true); + expect(ret.deviceId == "local").assertEqual(true); + done(); - g_object.setSessionId((error, data) => { - console.info(TAG + error + "," + data); - }); - g_object.name = undefined; - g_object.age = undefined; - g_object.isVis = undefined; - g_object.setSessionId("tmpsession1").then(() => { - console.info("join session"); - }).catch((error) => { - console.info(TAG + error.code + error.message); - }); + g_object.setSessionId(""); + g_object.name = undefined; + g_object.age = undefined; + g_object.isVis = undefined; + g_object.setSessionId("mySession1"); - expect(g_object.name == "Amy").assertEqual(true); - expect(g_object.age == 18).assertEqual(true); - expect(g_object.isVis == false).assertEqual(true); - console.log(TAG + "************* V9testSave001 end *************"); - g_object.setSessionId().then(() => { - console.info("leave session"); - }).catch((error) => { - console.info(TAG + error.code + error.message); + expect(g_object.name == "Amy").assertEqual(true); + expect(g_object.age == 18).assertEqual(true); + expect(g_object.isVis == false).assertEqual(true); + }).catch((err) => { + expect("801").assertEqual(err.code.toString()); + done(); }); + console.log(TAG + "************* V9testSave001 end *************"); }) /** @@ -503,20 +498,57 @@ describe('objectStoreTest', function () { * @tc.desc: test save local * @tc.type: FUNC */ - it('V9testSave002', 0, async function () { + it('V9testSave002', 0, async function (done) { console.log(TAG + "************* V9testSave002 start *************"); var g_object = distributedObject.create(context, {name: "Amy", age: 18, isVis: false}); expect(g_object == undefined).assertEqual(false); - g_object.setSessionId("tmpsession1").then(() => { + g_object.setSessionId("mySession2"); + expect("mySession2" == g_object.__sessionId).assertEqual(true); + + g_object.save("local", (err, result) => { + if (err) { + expect("801").assertEqual(err.code.toString()); + done(); + return; + } + expect(result.sessionId == "mySession2").assertEqual(true); + expect(result.version == g_object.__version).assertEqual(true); + expect(result.deviceId == "local").assertEqual(true); + + g_object.setSessionId(""); + g_object.name = undefined; + g_object.age = undefined; + g_object.isVis = undefined; + g_object.setSessionId("mySession2"); + + expect(g_object.name == "Amy").assertEqual(true); + expect(g_object.age == 18).assertEqual(true); + expect(g_object.isVis == false).assertEqual(true); + done(); + }); + console.log(TAG + "************* V9testSave002 end *************"); + }) + + /** + * @tc.name: V9testSave003 + * @tc.desc: test save local + * @tc.type: FUNC + */ + it('V9testSave003', 0, async function () { + console.log(TAG + "************* V9testSave003 start *************"); + var g_object = distributedObject.create(context, {name: "Amy", age: 18, isVis: false}); + expect(g_object == undefined).assertEqual(false); + + g_object.setSessionId("mySession3").then(() => { console.info("join session"); }).catch((error) => { console.info(TAG + error.code + error.message); }); - expect("tmpsession1" == g_object.__sessionId).assertEqual(true); + expect("mySession3" == g_object.__sessionId).assertEqual(true); try { g_object.save(1234).then((result) => { - expect(result.sessionId == "tmpsession1").assertEqual(true); + expect(result.sessionId == "mySession3").assertEqual(true); expect(result.version == g_object.__version).assertEqual(true); expect(result.deviceId == "local").assertEqual(true); }) @@ -524,20 +556,20 @@ describe('objectStoreTest', function () { expect(error.message == "Parameter error. The type of 'deviceId' must be 'string'.").assertEqual(true); } g_object.save("errorDeviceId").then((result) => { - expect(result.sessionId == "tmpsession1").assertEqual(true); + expect(result.sessionId == "mySession3").assertEqual(true); expect(result.version == g_object.__version).assertEqual(true); expect(result.deviceId == "local").assertEqual(true); }).catch((error) => { expect(error != undefined).assertEqual(true); }); - + try { g_object.save("local", 123); } catch (error) { expect(error.code == 401).assertEqual(true); expect(error.message == "Parameter error. The type of 'callback' must be 'function'.").assertEqual(true); } - console.log(TAG + "************* V9testSave002 end *************"); + console.log(TAG + "************* V9testSave003 end *************"); g_object.setSessionId().then(() => { console.info("leave session"); }).catch((error) => { @@ -550,81 +582,129 @@ describe('objectStoreTest', function () { * @tc.desc: test RevokeSave * @tc.type: FUNC */ - it('V9testRevokeSave001', 0, async function () { + it('V9testRevokeSave001', 0, async function (done) { console.log(TAG + "************* V9testRevokeSave001 start *************"); var g_object = distributedObject.create(context, {name: "Amy", age: 18, isVis: false}); expect(g_object == undefined).assertEqual(false); - g_object.setSessionId("123456").then(() => { - console.info("join session"); - }).catch((error) => { - console.info(TAG + error.code + error.message); + g_object.setSessionId("mySession4"); + expect("mySession4" == g_object.__sessionId).assertEqual(true); + + g_object.save("local", (err, result) => { + if (err) { + expect("801").assertEqual(err.code.toString()); + done(); + return; + } + expect(result.sessionId == "mySession4").assertEqual(true); + expect(result.version == g_object.__version).assertEqual(true); + expect(result.deviceId == "local").assertEqual(true); + g_object.revokeSave((err, result) => { + if (err) { + expect("801").assertEqual(err.code.toString()); + done(); + return; + } + expect("mySession4" == result.sessionId).assertEqual(true); + g_object.setSessionId(""); + g_object.name = undefined; + g_object.age = undefined; + g_object.isVis = undefined; + g_object.setSessionId("mySession4"); + + expect(g_object.name == undefined).assertEqual(true); + expect(g_object.age == undefined).assertEqual(true); + expect(g_object.isVis == undefined).assertEqual(true); + done(); + }) }); - expect("123456" == g_object.__sessionId).assertEqual(true); + console.log(TAG + "************* V9testRevokeSave001 end *************"); + }) - let result = await g_object.save("local"); - expect(result.sessionId == "123456").assertEqual(true); - expect(result.version == g_object.__version).assertEqual(true); - expect(result.deviceId == "local").assertEqual(true); - result = await g_object.revokeSave(); + /** + * @tc.name: V9testRevokeSave002 + * @tc.desc: test save local + * @tc.type: FUNC + * @tc.require: + */ + it('V9testRevokeSave002', 0, async function () { + console.log(TAG + "************* V9testRevokeSave002 start *************"); + var g_object = distributedObject.create(context, {name: "Amy", age: 18, isVis: false}); + expect(g_object != undefined).assertEqual(true); - g_object.setSessionId((error, data) => { - console.info(TAG + error + "," + data); + g_object.setSessionId("mySession5"); + expect("mySession5" == g_object.__sessionId.toString()).assertEqual(true); + + let result = await g_object.save("local").catch((err)=> { + expect("801").assertEqual(err.code.toString()); + return CATCH_ERR; }); + if (result === CATCH_ERR) { + return; + } + + expect(result.sessionId.toString() == "mySession5").assertEqual(true); + expect(result.version.toString() == g_object.__version.toString()).assertEqual(true); + expect(result.deviceId.toString() == "local").assertEqual(true); + + result = await g_object.revokeSave().catch((err)=> { + expect("801").assertEqual(err.code.toString()); + return CATCH_ERR; + }); + + if (result === CATCH_ERR) { + return; + } + g_object.setSessionId(""); g_object.name = undefined; g_object.age = undefined; g_object.isVis = undefined; - g_object.setSessionId("123456").then(() => { - console.info("join session"); - }).catch((error) => { - console.info(TAG + error.code + error.message); - }); + g_object.setSessionId("mySession5"); expect(g_object.name == undefined).assertEqual(true); expect(g_object.age == undefined).assertEqual(true); expect(g_object.isVis == undefined).assertEqual(true); - expect(result.sessionId == "123456").assertEqual(true); - console.log(TAG + "************* V9testRevokeSave001 end *************"); - g_object.setSessionId("", (error, data) => { - console.info(TAG + error + "," + data); - }); + + console.log(TAG + "************* V9testRevokeSave002 end *************"); }) /** - * @tc.name: V9testRevokeSave002 + * @tc.name: V9testRevokeSave003 * @tc.desc: test RevokeSave * @tc.type: FUNC */ - it('V9testRevokeSave002', 0, async function () { - console.log(TAG + "************* V9testRevokeSave002 start *************"); + it('V9testRevokeSave003', 0, async function () { + console.log(TAG + "************* V9testRevokeSave003 start *************"); var g_object = distributedObject.create(context, {name: "Amy", age: 18, isVis: false}); expect(g_object == undefined).assertEqual(false); - g_object.setSessionId("123456").then(() => { + g_object.setSessionId("mySession6").then(() => { console.info("join session"); }).catch((error) => { console.info(TAG + error.code + error.message); }); - expect("123456" == g_object.__sessionId).assertEqual(true); - let result = await g_object.save("local"); - expect(result.sessionId == "123456").assertEqual(true); + expect("mySession6" == g_object.__sessionId).assertEqual(true); + let result = await g_object.save("local").catch((err) => { + expect("801").assertEqual(err.code.toString()); + return CATCH_ERR; + }); + if (result === CATCH_ERR) { + return; + } + expect(result.sessionId == "mySession6").assertEqual(true); expect(result.version == g_object.__version).assertEqual(true); expect(result.deviceId == "local").assertEqual(true); try { g_object.revokeSave(123).then((result) => { - expect(result.sessionId == "tmpsession1").assertEqual(true) + expect(result.sessionId == "mySession6").assertEqual(true); }).catch((err) => { console.log(err.code + err.message); }); } catch (error) { console.info(error.code + error.message); - expect(error.code == 401).assertEqual(true); - expect(error.message == "Parameter error. The type of 'callback' must be 'function'.").assertEqual(true); + expect("401").assertEqual(error.code.toString()); } - console.log(TAG + "************* V9testRevokeSave002 end *************"); - g_object.setSessionId("", (error, data) => { - console.info(TAG + error + "," + data); - }); + console.log(TAG + "************* V9testRevokeSave003 end *************"); }) - + console.log(TAG + "*************Unit Test End*************"); }) \ No newline at end of file diff --git a/data_object/interfaces/jskits/BUILD.gn b/data_object/interfaces/jskits/BUILD.gn index 5a3ea00d..52f503a4 100644 --- a/data_object/interfaces/jskits/BUILD.gn +++ b/data_object/interfaces/jskits/BUILD.gn @@ -118,6 +118,7 @@ ohos_shared_library("distributeddataobject") { "ability_runtime:app_context", "ability_runtime:napi_base_context", "access_token:libaccesstoken_sdk", + "common_event_service:cesfwk_innerkits", "hiviewdfx_hilog_native:libhilog", "napi:ace_napi", ] diff --git a/data_object/interfaces/jskits/distributed_data_object.js b/data_object/interfaces/jskits/distributed_data_object.js index a7e2a89f..f32a1ce4 100644 --- a/data_object/interfaces/jskits/distributed_data_object.js +++ b/data_object/interfaces/jskits/distributed_data_object.js @@ -13,328 +13,331 @@ * limitations under the License. */ -const distributedObject = requireInternal("data.distributedDataObject"); -const SESSION_ID = "__sessionId"; -const VERSION = "__version"; -const COMPLEX_TYPE = "[COMPLEX]"; -const STRING_TYPE = "[STRING]"; -const NULL_TYPE = "[NULL]" +const distributedObject = requireInternal('data.distributedDataObject'); +const SESSION_ID = '__sessionId'; +const VERSION = '__version'; +const COMPLEX_TYPE = '[COMPLEX]'; +const STRING_TYPE = '[STRING]'; +const NULL_TYPE = '[NULL]'; const JS_ERROR = 1; +const SDK_VERSION_8 = 8; +const SDK_VERSION_9 = 9; class Distributed { - constructor(obj) { - constructorMethod(this, obj); - } + constructor(obj) { + constructorMethod(this, obj); + } - setSessionId(sessionId) { - if (sessionId == null || sessionId == "") { - leaveSession(this.__sdkVersion, this.__proxy); - return false; - } - if (this.__proxy[SESSION_ID] == sessionId) { - console.info("same session has joined " + sessionId); - return true; - } - leaveSession(this.__sdkVersion, this.__proxy); - let object = joinSession(this.__sdkVersion, this.__proxy, this.__objectId, sessionId); - if (object != null) { - this.__proxy = object; - return true; - } - return false; + setSessionId(sessionId) { + if (sessionId == null || sessionId === '') { + leaveSession(this.__sdkVersion, this.__proxy); + return false; } - - on(type, callback) { - onWatch(this.__sdkVersion, type, this.__proxy, callback); - distributedObject.recordCallback(this.__sdkVersion, type, this.__objectId, callback); + if (this.__proxy[SESSION_ID] === sessionId) { + console.info('same session has joined ' + sessionId); + return true; + } + leaveSession(this.__sdkVersion, this.__proxy); + let object = joinSession(this.__sdkVersion, this.__proxy, this.__objectId, sessionId); + if (object != null) { + this.__proxy = object; + return true; } + return false; + } - off(type, callback) { - offWatch(this.__sdkVersion, type, this.__proxy, callback); - if (callback != undefined || callback != null) { - distributedObject.deleteCallback(this.__sdkVersion, type, this.__objectId, callback); - } else { - distributedObject.deleteCallback(this.__sdkVersion, type, this.__objectId); - } + on(type, callback) { + onWatch(this.__sdkVersion, type, this.__proxy, callback); + distributedObject.recordCallback(this.__sdkVersion, type, this.__objectId, callback); + } + + off(type, callback) { + offWatch(this.__sdkVersion, type, this.__proxy, callback); + if (callback !== undefined || callback != null) { + distributedObject.deleteCallback(this.__sdkVersion, type, this.__objectId, callback); + } else { + distributedObject.deleteCallback(this.__sdkVersion, type, this.__objectId); } + } - save(deviceId, callback) { - if (this.__proxy[SESSION_ID] == null || this.__proxy[SESSION_ID] == "") { - console.info("not join a session, can not do save"); - return JS_ERROR; - } - return this.__proxy.save(deviceId, this[VERSION], callback); + save(deviceId, callback) { + if (this.__proxy[SESSION_ID] == null || this.__proxy[SESSION_ID] === '') { + console.info('not join a session, can not do save'); + return JS_ERROR; } + return this.__proxy.save(deviceId, this[VERSION], callback); + } - revokeSave(callback) { - if (this.__proxy[SESSION_ID] == null || this.__proxy[SESSION_ID] == "") { - console.info("not join a session, can not do revoke save"); - return JS_ERROR; - } - return this.__proxy.revokeSave(callback); + revokeSave(callback) { + if (this.__proxy[SESSION_ID] == null || this.__proxy[SESSION_ID] === '') { + console.info('not join a session, can not do revoke save'); + return JS_ERROR; } + return this.__proxy.revokeSave(callback); + } - __proxy; - __objectId; - __version; - __sdkVersion = 8 ; + __proxy; + __objectId; + __version; + __sdkVersion = SDK_VERSION_8; } function constructorMethod(result, obj) { - result.__proxy = obj; - Object.keys(obj).forEach(key => { - Object.defineProperty(result, key, { - enumerable: true, - configurable: true, - get: function () { - return result.__proxy[key]; - }, - set: function (newValue) { - result[VERSION]++; - result.__proxy[key] = newValue; - } - }); + result.__proxy = obj; + Object.keys(obj).forEach(key => { + Object.defineProperty(result, key, { + enumerable: true, + configurable: true, + get: function () { + return result.__proxy[key]; + }, + set: function (newValue) { + result[VERSION]++; + result.__proxy[key] = newValue; + } }); - Object.defineProperty(result, SESSION_ID, { - enumerable: true, - configurable: true, - get: function () { - return result.__proxy[SESSION_ID]; - }, - set: function (newValue) { - result.__proxy[SESSION_ID] = newValue; - } - }); - result.__objectId = randomNum(); - result[VERSION] = 0; - console.info("constructor success "); + }); + Object.defineProperty(result, SESSION_ID, { + enumerable: true, + configurable: true, + get: function () { + return result.__proxy[SESSION_ID]; + }, + set: function (newValue) { + result.__proxy[SESSION_ID] = newValue; + } + }); + result.__objectId = randomNum(); + result[VERSION] = 0; + console.info('constructor success '); } function randomNum() { - return distributedObject.sequenceNum(); + return distributedObject.sequenceNum(); } function newDistributed(obj) { - console.info("start newDistributed"); - if (obj == null) { - console.error("object is null"); - return null; - } - return new Distributed(obj); + console.info('start newDistributed'); + if (obj == null) { + console.error('object is null'); + return null; + } + return new Distributed(obj); } function joinSession(version, obj, objectId, sessionId, context) { - console.info("start joinSession " + sessionId); - if (obj == null || sessionId == null || sessionId == "") { - console.error("object is null"); - return null; - } + console.info('start joinSession ' + sessionId); + if (obj == null || sessionId == null || sessionId === '') { + console.error('object is null'); + return null; + } - let object = null; - if (context != undefined || context != null) { - object = distributedObject.createObjectSync(version, sessionId, objectId, context); - } else { - object = distributedObject.createObjectSync(version, sessionId, objectId); - } + let object = null; + if (context !== undefined || context != null) { + object = distributedObject.createObjectSync(version, sessionId, objectId, context); + } else { + object = distributedObject.createObjectSync(version, sessionId, objectId); + } - if (object == null) { - console.error("create fail"); - return null; - } - Object.keys(obj).forEach(key => { - console.info("start define " + key); - Object.defineProperty(object, key, { - enumerable: true, - configurable: true, - get: function () { - console.info("start get " + key); - let result = object.get(key); - console.info("get " + result); - if (typeof result == "string") { - if (result.startsWith(STRING_TYPE)) { - result = result.substr(STRING_TYPE.length); - } else if (result.startsWith(COMPLEX_TYPE)) { - result = JSON.parse(result.substr(COMPLEX_TYPE.length)) - } else if (result.startsWith(NULL_TYPE)) { - result = null; - } else { - console.error("error type " + result); - } - } - console.info("get " + result + " success"); - return result; - }, - set: function (newValue) { - console.info("start set " + key + " " + newValue); - if (typeof newValue == "object") { - let value = COMPLEX_TYPE + JSON.stringify(newValue); - object.put(key, value); - console.info("set " + key + " " + value); - } else if (typeof newValue == "string") { - let value = STRING_TYPE + newValue; - object.put(key, value); - console.info("set " + key + " " + value); - } else if (newValue === null) { - let value = NULL_TYPE; - object.put(key, value); - console.info("set " + key + " " + value); - } else { - object.put(key, newValue); - console.info("set " + key + " " + newValue); - } - } - }); - if (obj[key] != undefined) { - object[key] = obj[key]; + if (object == null) { + console.error('create fail'); + return null; + } + Object.keys(obj).forEach(key => { + console.info('start define ' + key); + Object.defineProperty(object, key, { + enumerable: true, + configurable: true, + get: function () { + console.info('start get ' + key); + let result = object.get(key); + console.info('get ' + result); + if (typeof result === 'string') { + if (result.startsWith(STRING_TYPE)) { + result = result.substr(STRING_TYPE.length); + } else if (result.startsWith(COMPLEX_TYPE)) { + result = JSON.parse(result.substr(COMPLEX_TYPE.length)); + } else if (result.startsWith(NULL_TYPE)) { + result = null; + } else { + console.error('error type ' + result); + } } + console.info('get ' + result + ' success'); + return result; + }, + set: function (newValue) { + console.info('start set ' + key + ' ' + newValue); + if (typeof newValue === 'object') { + let value = COMPLEX_TYPE + JSON.stringify(newValue); + object.put(key, value); + console.info('set ' + key + ' ' + value); + } else if (typeof newValue === 'string') { + let value = STRING_TYPE + newValue; + object.put(key, value); + console.info('set ' + key + ' ' + value); + } else if (newValue == null) { + let value = NULL_TYPE; + object.put(key, value); + console.info('set ' + key + ' ' + value); + } else { + object.put(key, newValue); + console.info('set ' + key + ' ' + newValue); + } + } }); + if (obj[key] !== undefined) { + object[key] = obj[key]; + } + }); - Object.defineProperty(object, SESSION_ID, { - value: sessionId, - configurable: true, - }); - return object; + Object.defineProperty(object, SESSION_ID, { + value: sessionId, + configurable: true, + }); + return object; } function leaveSession(version, obj) { - console.info("start leaveSession"); - if (obj == null || obj[SESSION_ID] == null || obj[SESSION_ID] == "") { - console.warn("object is null"); - return; - } - Object.keys(obj).forEach(key => { - Object.defineProperty(obj, key, { - value: obj[key], - configurable: true, - writable: true, - enumerable: true, - }); + console.info('start leaveSession'); + if (obj == null || obj[SESSION_ID] == null || obj[SESSION_ID] === '') { + console.warn('object is null'); + return; + } + Object.keys(obj).forEach(key => { + Object.defineProperty(obj, key, { + value: obj[key], + configurable: true, + writable: true, + enumerable: true, }); - // disconnect,delete object - distributedObject.destroyObjectSync(version, obj); - delete obj[SESSION_ID]; + }); + // disconnect,delete object + distributedObject.destroyObjectSync(version, obj); + delete obj[SESSION_ID]; } function onWatch(version, type, obj, callback) { - console.info("start on " + obj[SESSION_ID]); - if (obj[SESSION_ID] != null && obj[SESSION_ID] != undefined && obj[SESSION_ID].length > 0) { - distributedObject.on(version, type, obj, callback); - } + console.info('start on ' + obj[SESSION_ID]); + if (obj[SESSION_ID] != null && obj[SESSION_ID] !== undefined && obj[SESSION_ID].length > 0) { + distributedObject.on(version, type, obj, callback); + } } function offWatch(version, type, obj, callback = undefined) { - console.info("start off " + obj[SESSION_ID] + " " + callback); - if (obj[SESSION_ID] != null && obj[SESSION_ID] != undefined && obj[SESSION_ID].length > 0) { - if (callback != undefined || callback != null) { - distributedObject.off(version, type, obj, callback); - } else { - distributedObject.off(version, type, obj); - } + console.info('start off ' + obj[SESSION_ID] + ' ' + callback); + if (obj[SESSION_ID] != null && obj[SESSION_ID] !== undefined && obj[SESSION_ID].length > 0) { + if (callback !== undefined || callback != null) { + distributedObject.off(version, type, obj, callback); + } else { + distributedObject.off(version, type, obj); } + } } function newDistributedV9(context, obj) { - console.info("start newDistributed"); - let checkparameter = function(parameter, type) { - throw { code : 401, - message :"Parameter error. The type of '" + parameter + "' must be '" + type + "'."}; - } - if(typeof context != "object") { - checkparameter("context", "Context"); - } - if(typeof obj != "object") { - checkparameter("source", "object"); - } - if (obj == null) { - console.error("object is null"); - return null; - } - return new DistributedV9(obj, context); + console.info('start newDistributed'); + let checkparameter = function(parameter, type) { + throw { + code: 401, + message :"Parameter error. The type of '" + parameter + "' must be '" + type + "'."}; + }; + if (typeof context !== 'object') { + checkparameter('context', 'Context'); + } + if (typeof obj !== 'object') { + checkparameter('source', 'object'); + } + if (obj == null) { + console.error('object is null'); + return null; + } + return new DistributedV9(obj, context); } class DistributedV9 { - constructor(obj, context) { - this.__context = context; - constructorMethod(this, obj); - } + constructor(obj, context) { + this.__context = context; + constructorMethod(this, obj); + } - setSessionId(sessionId, callback) { - if (typeof sessionId == "function" || sessionId == null || sessionId == "") { - leaveSession(this.__sdkVersion, this.__proxy); - if (typeof sessionId == "function") { - return sessionId(this.__proxy); - } else if (typeof callback == "function") { - return callback(null, this.__proxy); - } else { - return Promise.resolve(null, this.__proxy); - } - } - if (this.__proxy[SESSION_ID] == sessionId) { - console.info("same session has joined " + sessionId); - if (typeof callback == "function") { - return callback(null, this.__proxy); - } else { - return Promise.resolve(null, this.__proxy); - } - } - leaveSession(this.__sdkVersion, this.__proxy); - let object = joinSession(this.__sdkVersion, this.__proxy, this.__objectId, sessionId, this.__context); - if (object != null) { - this.__proxy = object; - if (typeof callback == "function") { - return callback(null, this.__proxy) - } else { - return Promise.resolve(null, object); - } - } else { - if (typeof callback == "function") { - return callback(null, null); - } else { - return Promise.reject(null, null); - } - } + setSessionId(sessionId, callback) { + if (typeof sessionId === 'function' || sessionId == null || sessionId === '') { + leaveSession(this.__sdkVersion, this.__proxy); + if (typeof sessionId === 'function') { + return sessionId(this.__proxy); + } else if (typeof callback === 'function') { + return callback(null, this.__proxy); + } else { + return Promise.resolve(null, this.__proxy); + } } - - on(type, callback) { - onWatch(this.__sdkVersion, type, this.__proxy, callback); - distributedObject.recordCallback(this.__sdkVersion, type, this.__objectId, callback); + if (this.__proxy[SESSION_ID] === sessionId) { + console.info('same session has joined ' + sessionId); + if (typeof callback === 'function') { + return callback(null, this.__proxy); + } else { + return Promise.resolve(null, this.__proxy); + } } + leaveSession(this.__sdkVersion, this.__proxy); + let object = joinSession(this.__sdkVersion, this.__proxy, this.__objectId, sessionId, this.__context); + if (object != null) { + this.__proxy = object; + if (typeof callback === 'function') { + return callback(null, this.__proxy); + } else { + return Promise.resolve(null, object); + } + } else { + if (typeof callback === 'function') { + return callback(null, null); + } else { + return Promise.reject(null, null); + } + } + } - off(type, callback) { - offWatch(this.__sdkVersion, type, this.__proxy, callback); - if (callback != undefined || callback != null) { - distributedObject.deleteCallback(this.__sdkVersion, type, this.__objectId, callback); - } else { - distributedObject.deleteCallback(this.__sdkVersion, type, this.__objectId); - } + on(type, callback) { + onWatch(this.__sdkVersion, type, this.__proxy, callback); + distributedObject.recordCallback(this.__sdkVersion, type, this.__objectId, callback); + } + + off(type, callback) { + offWatch(this.__sdkVersion, type, this.__proxy, callback); + if (callback !== undefined || callback != null) { + distributedObject.deleteCallback(this.__sdkVersion, type, this.__objectId, callback); + } else { + distributedObject.deleteCallback(this.__sdkVersion, type, this.__objectId); } + } - save(deviceId, callback) { - if (this.__proxy[SESSION_ID] == null || this.__proxy[SESSION_ID] == "") { - console.info("not join a session, can not do save"); - return JS_ERROR; - } - return this.__proxy.save(deviceId, this[VERSION], callback); + save(deviceId, callback) { + if (this.__proxy[SESSION_ID] == null || this.__proxy[SESSION_ID] === '') { + console.info('not join a session, can not do save'); + return JS_ERROR; } + return this.__proxy.save(deviceId, this[VERSION], callback); + } - revokeSave(callback) { - if (this.__proxy[SESSION_ID] == null || this.__proxy[SESSION_ID] == "") { - console.info("not join a session, can not do revoke save"); - return JS_ERROR; - } - return this.__proxy.revokeSave(callback); + revokeSave(callback) { + if (this.__proxy[SESSION_ID] == null || this.__proxy[SESSION_ID] === '') { + console.info('not join a session, can not do revoke save'); + return JS_ERROR; } + return this.__proxy.revokeSave(callback); + } - __context; - __proxy; - __objectId; - __version; - __sdkVersion = 9; + __context; + __proxy; + __objectId; + __version; + __sdkVersion = SDK_VERSION_9; } export default { - createDistributedObject: newDistributed, - create: newDistributedV9, - genSessionId: randomNum -} \ No newline at end of file + createDistributedObject: newDistributed, + create: newDistributedV9, + genSessionId: randomNum +}; diff --git a/data_object/samples/distributedNotepad/ReadMe.md b/data_object/samples/distributedNotepad/ReadMe.md index 06f24a7b..247fe16e 100644 --- a/data_object/samples/distributedNotepad/ReadMe.md +++ b/data_object/samples/distributedNotepad/ReadMe.md @@ -150,10 +150,10 @@ changeCallback(sessionId, changeData) { changeData.forEach(element => { if (element == "documentList") { // 刷新界面上的备忘录数据列表 - this.dataModel.documentList = distr.g_dataModel.distributedObject.documentList; + this.dataModel.documentList = distr.dataModel.distributedObject.documentList; } else if (element == "documentSize") { - let size = distr.g_dataModel.distributedObject.documentSize; + let size = distr.dataModel.distributedObject.documentSize; // 刷新界面上列表总数 this.dataModel.distributedObject.documentSize = size; } @@ -168,9 +168,9 @@ changeCallback(sessionId, changeData) { onInit() { // 监听对端设备的数据变更 // 发起方要在changeCallback里刷新界面,则需要将正确的this绑定给changeCallback - distr.g_dataModel.setCallback(this.changeCallback.bind(this)); + distr.dataModel.setCallback(this.changeCallback.bind(this)); // 监听分布式对象的上下线状态 - distr.g_dataModel.setStatusCallback((sessionId, networkId, status) => { + distr.dataModel.setStatusCallback((sessionId, networkId, status) => { // 刷新红绿灯界面 if (status == "online") { this.dataModel.imgSrc = "common/green.png"; @@ -188,7 +188,7 @@ onInit() { ```js doAdd: function () { - distr.g_dataModel.add(this.title, this.content); + distr.dataModel.add(this.title, this.content); ... } ``` @@ -209,7 +209,7 @@ add(title, content) { ```js save: function () { // 使用页面数据更新分布式对象属性数据 - distr.g_dataModel.update(this.editIndex, this.title, this.content); + distr.dataModel.update(this.editIndex, this.title, this.content); ... } ``` @@ -230,7 +230,7 @@ update(index, title, content) { clear: function () { // 触发界面刷新 this.dataModel.documentList = []; - distr.g_dataModel.clear(); + distr.dataModel.clear(); this.dataModel.distributedObject.documentSize = 0; }, ``` diff --git a/data_object/samples/distributedNotepad/entry/src/main/js/MainAbility/app.js b/data_object/samples/distributedNotepad/entry/src/main/js/MainAbility/app.js index e3a0891c..b8b9fcdb 100644 --- a/data_object/samples/distributedNotepad/entry/src/main/js/MainAbility/app.js +++ b/data_object/samples/distributedNotepad/entry/src/main/js/MainAbility/app.js @@ -14,10 +14,10 @@ */ export default { - onCreate() { - console.info("Application onCreate"); - }, - onDestroy() { - console.info("Application onDestroy"); - } + onCreate() { + console.info('Application onCreate'); + }, + onDestroy() { + console.info('Application onDestroy'); + } }; diff --git a/data_object/samples/distributedNotepad/entry/src/main/js/MainAbility/pages/add/add.js b/data_object/samples/distributedNotepad/entry/src/main/js/MainAbility/pages/add/add.js index 1dcc4d7a..073c120b 100644 --- a/data_object/samples/distributedNotepad/entry/src/main/js/MainAbility/pages/add/add.js +++ b/data_object/samples/distributedNotepad/entry/src/main/js/MainAbility/pages/add/add.js @@ -13,30 +13,30 @@ * limitations under the License. */ -import router from '@system.router' -import * as distr from '../../../model/DistributedDataModel.js' +import router from '@system.router'; +import * as distr from '../../../model/DistributedDataModel.js'; export default { - data: { - title: "天气不错奥", - content: "今天天气不错" - }, - onInit() { - console.info("objectstore in add page"); - }, - doAdd: function () { - console.info("doAdd " + JSON.stringify(distr.g_dataModel)); - distr.g_dataModel.add(this.title, this.content); - router.replace({ - uri: "pages/index/index", - params: { - dataModel: distr.g_dataModel - } - }) - }, - changeTitle: function (e) { - this.title = e.text; - }, - changeContent: function (e) { - this.content = e.text; - } -} + data: { + title: '天气不错奥', + content: '今天天气不错' + }, + onInit() { + console.info('objectstore in add page'); + }, + doAdd: function () { + console.info('doAdd ' + JSON.stringify(distr.dataModel)); + distr.dataModel.add(this.title, this.content); + router.replace({ + uri: 'pages/index/index', + params: { + dataModel: distr.dataModel + } + }); + }, + changeTitle: function (e) { + this.title = e.text; + }, + changeContent: function (e) { + this.content = e.text; + } +}; diff --git a/data_object/samples/distributedNotepad/entry/src/main/js/MainAbility/pages/detail/detail.js b/data_object/samples/distributedNotepad/entry/src/main/js/MainAbility/pages/detail/detail.js index 461f1798..a808b7a0 100644 --- a/data_object/samples/distributedNotepad/entry/src/main/js/MainAbility/pages/detail/detail.js +++ b/data_object/samples/distributedNotepad/entry/src/main/js/MainAbility/pages/detail/detail.js @@ -13,40 +13,40 @@ * limitations under the License. */ -import router from '@system.router' -import * as distr from '../../../model/DistributedDataModel.js' +import router from '@system.router'; +import * as distr from '../../../model/DistributedDataModel.js'; export default { - data: { - title: "天气不错奥", - content: "今天天气不错", - edit: "保存" - }, - onInit() { - console.info("objectstore in detail page"); - }, - back: function () { - router.replace({ - uri: "pages/index/index", - params: { - dataModel: distr.g_dataModel - } - }) - }, - change: function (e) { - this.title = e.text; - }, - changeContent: function (e) { - this.content = e.text; - }, - save: function () { - console.info("start save "+ JSON.stringify(this.data)); - distr.g_dataModel.update(this.editIndex, this.title, this.content); - router.replace({ - uri: "pages/index/index", - params: { - dataModel: distr.g_dataModel - } - }) - } -} + data: { + title: '天气不错奥', + content: '今天天气不错', + edit: '保存' + }, + onInit() { + console.info('objectstore in detail page'); + }, + back: function () { + router.replace({ + uri: 'pages/index/index', + params: { + dataModel: distr.dataModel + } + }); + }, + change: function (e) { + this.title = e.text; + }, + changeContent: function (e) { + this.content = e.text; + }, + save: function () { + console.info('start save ' + JSON.stringify(this.data)); + distr.dataModel.update(this.editIndex, this.title, this.content); + router.replace({ + uri: 'pages/index/index', + params: { + dataModel: distr.dataModel + } + }); + } +}; diff --git a/data_object/samples/distributedNotepad/entry/src/main/js/MainAbility/pages/index/index.js b/data_object/samples/distributedNotepad/entry/src/main/js/MainAbility/pages/index/index.js index 0818c296..c0b22239 100644 --- a/data_object/samples/distributedNotepad/entry/src/main/js/MainAbility/pages/index/index.js +++ b/data_object/samples/distributedNotepad/entry/src/main/js/MainAbility/pages/index/index.js @@ -13,69 +13,69 @@ * limitations under the License. */ -import router from '@system.router' -import * as distr from '../../../model/DistributedDataModel.js' +import router from '@system.router'; +import * as distr from '../../../model/DistributedDataModel.js'; export default { - data: { - dataModel: distr.g_dataModel - }, - changeCallback(sessionId, changeData) { - changeData.forEach(element => { - if (element == "documentList") { - console.info("newest data " + JSON.stringify(this.dataModel.distributedObject.documentList)); - // 触发界面刷新 - this.dataModel.documentList = distr.g_dataModel.distributedObject.documentList; - } else if (element == "documentSize") { - let size = distr.g_dataModel.distributedObject.documentSize; - console.info("newest size " + size); - // 触发界面刷新 - this.dataModel.distributedObject.documentSize = size; - } - }); - }, - onInit() { - console.info("objectstore in index page "); - console.info(JSON.stringify(this.dataModel.documentList)); - console.info(JSON.stringify(distr.g_dataModel.distributedObject.documentList)); - distr.g_dataModel.setCallback(this.changeCallback.bind(this)); - distr.g_dataModel.setStatusCallback((sessionId, networkId, status) => { - console.info("objectstore status change ${networkId} ${status}"); - if (status == "online") { - this.dataModel.imgSrc = "common/green.png"; - } else { - this.dataModel.imgSrc = "common/red.png"; - } - }) - }, - onDestroy() { - console.info("objectstore exit index page"); - distr.g_dataModel.clearCallback(); - }, - add: function () { - router.replace({ - uri: "pages/add/add" - }) - }, - clear: function () { + data: { + dataModel: distr.dataModel + }, + changeCallback(sessionId, changeData) { + changeData.forEach(element => { + if (element === 'documentList') { + console.info('newest data ' + JSON.stringify(this.dataModel.distributedObject.documentList)); // 触发界面刷新 - this.dataModel.documentList = []; - this.dataModel.distributedObject.documentSize = 0; - distr.g_dataModel.clear(); - }, - detail: function (msg) { - router.replace({ - uri: "pages/detail/detail", - params: { - title: msg.target.dataSet.title, - content: msg.target.dataSet.content, - oriTitle: msg.target.dataSet.title, - oriContent: msg.target.dataSet.content, - editIndex: msg.target.dataSet.index - } - }) - } -} + this.dataModel.documentList = distr.dataModel.distributedObject.documentList; + } else if (element === 'documentSize') { + let size = distr.dataModel.distributedObject.documentSize; + console.info('newest size ' + size); + // 触发界面刷新 + this.dataModel.distributedObject.documentSize = size; + } + }); + }, + onInit() { + console.info('objectstore in index page '); + console.info(JSON.stringify(this.dataModel.documentList)); + console.info(JSON.stringify(distr.dataModel.distributedObject.documentList)); + distr.dataModel.setCallback(this.changeCallback.bind(this)); + distr.dataModel.setStatusCallback((sessionId, networkId, status) => { + console.info('objectstore status change ${networkId} ${status}'); + if (status === 'online') { + this.dataModel.imgSrc = 'common/green.png'; + } else { + this.dataModel.imgSrc = 'common/red.png'; + } + }); + }, + onDestroy() { + console.info('objectstore exit index page'); + distr.dataModel.clearCallback(); + }, + add: function () { + router.replace({ + uri: 'pages/add/add' + }); + }, + clear: function () { + // 触发界面刷新 + this.dataModel.documentList = []; + this.dataModel.distributedObject.documentSize = 0; + distr.dataModel.clear(); + }, + detail: function (msg) { + router.replace({ + uri: 'pages/detail/detail', + params: { + title: msg.target.dataSet.title, + content: msg.target.dataSet.content, + oriTitle: msg.target.dataSet.title, + oriContent: msg.target.dataSet.content, + editIndex: msg.target.dataSet.index + } + }); + } +}; diff --git a/data_object/samples/distributedNotepad/entry/src/main/js/model/DistributedDataModel.js b/data_object/samples/distributedNotepad/entry/src/main/js/model/DistributedDataModel.js index 9881d32c..e6b4e05d 100644 --- a/data_object/samples/distributedNotepad/entry/src/main/js/model/DistributedDataModel.js +++ b/data_object/samples/distributedNotepad/entry/src/main/js/model/DistributedDataModel.js @@ -13,106 +13,108 @@ * limitations under the License. */ -import distributedObject from '@ohos.data.distributedDataObject' +import distributedObject from '@ohos.data.distributedDataObject'; import featureAbility from '@ohos.ability.featureAbility'; +const REQUEST_MODE = 666; + function grantPermission() { - console.info('grantPermission'); - let context = featureAbility.getContext(); - context.requestPermissionsFromUser(['ohos.permission.DISTRIBUTED_DATASYNC'], 666, function (result) { - console.info(`result.requestCode=${result.requestCode}`) + console.info('grantPermission'); + let context = featureAbility.getContext(); + context.requestPermissionsFromUser(['ohos.permission.DISTRIBUTED_DATASYNC'], REQUEST_MODE, function (result) { + console.info(`result.requestCode=${result.requestCode}`); - }) - console.info('end grantPermission'); + }); + console.info('end grantPermission'); } export default class DistributedDataModel { - documentList = []; - distributedObject; // distributed proxy - imgSrc = "common/red.png"; - #callback; - #statusCallback; + documentList = []; + distributedObject; // distributed proxy + imgSrc = 'common/red.png'; + #callback; + #statusCallback; - constructor() { - this.distributedObject = distributedObject.createDistributedObject({ - documentList: this.documentList, - documentSize: 0 - }); - this.share(); - } + constructor() { + this.distributedObject = distributedObject.createDistributedObject({ + documentList: this.documentList, + documentSize: 0 + }); + this.share(); + } - clearCallback() { - this.distributedObject.off("change"); - this.#callback = undefined; - this.distributedObject.off("status"); - this.#statusCallback = undefined; - } + clearCallback() { + this.distributedObject.off('change'); + this.#callback = undefined; + this.distributedObject.off('status'); + this.#statusCallback = undefined; + } - setCallback(callback) { - if (this.#callback == callback) { - console.info("same callback"); - return; - } - console.info("start off"); - if (this.#callback != undefined) { - this.distributedObject.off("change", this.#callback); - } - this.#callback = callback; - console.info("start watch change"); - this.distributedObject.on("change", this.#callback); + setCallback(callback) { + if (this.#callback === callback) { + console.info('same callback'); + return; } - - setStatusCallback(callback) { - if (this.#statusCallback == callback) { - console.info("same callback"); - return; - } - console.info("start off"); - if (this.#statusCallback != undefined) { - this.distributedObject.off("status", this.#statusCallback); - } - this.#statusCallback = callback; - console.info("start watch change"); - this.distributedObject.on("status", this.#statusCallback); + console.info('start off'); + if (this.#callback !== undefined) { + this.distributedObject.off('change', this.#callback); } + this.#callback = callback; + console.info('start watch change'); + this.distributedObject.on('change', this.#callback); + } - share() { - console.info("start share"); - if (this.distributedObject.__sessionId == undefined) { - grantPermission() - this.distributedObject.setSessionId("123456") - } + setStatusCallback(callback) { + if (this.#statusCallback === callback) { + console.info('same callback'); + return; } - - update(index, title, content) { - console.info("doUpdate " + title + index); - this.documentList = this.distributedObject.documentList; - this.documentList[index] = { - index: index, title: title, content: content - }; - this.distributedObject.documentList = this.documentList; - console.info("update my documentList " + JSON.stringify(this.documentList)); + console.info('start off'); + if (this.#statusCallback !== undefined) { + this.distributedObject.off('status', this.#statusCallback); } + this.#statusCallback = callback; + console.info('start watch change'); + this.distributedObject.on('status', this.#statusCallback); + } - add(title, content) { - console.info("doAdd " + title + content); - console.info("documentList " + JSON.stringify(this.documentList)); - this.documentList = this.distributedObject.documentList; - this.documentList[this.distributedObject.documentSize] = { - index: this.distributedObject.documentSize, title: title, content: content - }; - this.distributedObject.documentList = this.documentList; - this.distributedObject.documentSize++; - console.info("add my documentList " + JSON.stringify(this.documentList)); - } + share() { + console.info('start share'); + if (this.distributedObject.__sessionId === undefined) { + grantPermission(); + this.distributedObject.setSessionId('123456'); + } + } + update(index, title, content) { + console.info('doUpdate ' + title + index); + this.documentList = this.distributedObject.documentList; + this.documentList[index] = { + index: index, title: title, content: content + }; + this.distributedObject.documentList = this.documentList; + console.info('update my documentList ' + JSON.stringify(this.documentList)); + } - clear() { - console.info("doClear "); - this.documentList = []; - this.distributedObject.documentList = this.documentList; - this.distributedObject.documentSize = 0; - console.info("doClear finish"); - } + add(title, content) { + console.info('doAdd ' + title + content); + console.info('documentList ' + JSON.stringify(this.documentList)); + this.documentList = this.distributedObject.documentList; + this.documentList[this.distributedObject.documentSize] = { + index: this.distributedObject.documentSize, title: title, content: content + }; + this.distributedObject.documentList = this.documentList; + this.distributedObject.documentSize++; + console.info('add my documentList ' + JSON.stringify(this.documentList)); + } + + + clear() { + console.info('doClear '); + this.documentList = []; + this.distributedObject.documentList = this.documentList; + this.distributedObject.documentSize = 0; + console.info('doClear finish'); + } } -export var g_dataModel = new DistributedDataModel(); \ No newline at end of file +export let dataModel = new DistributedDataModel(); \ No newline at end of file diff --git a/data_share/frameworks/js/napi/common/src/datashare_predicates_proxy.cpp b/data_share/frameworks/js/napi/common/src/datashare_predicates_proxy.cpp index a0c92820..13e22552 100644 --- a/data_share/frameworks/js/napi/common/src/datashare_predicates_proxy.cpp +++ b/data_share/frameworks/js/napi/common/src/datashare_predicates_proxy.cpp @@ -85,7 +85,11 @@ napi_value DataSharePredicatesProxy::New(napi_env env, napi_callback_info info) NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &thiz, nullptr)); if (is_constructor) { - auto *proxy = new DataSharePredicatesProxy(); + auto *proxy = new (std::nothrow) DataSharePredicatesProxy(); + if (proxy == nullptr) { + LOG_ERROR("DataSharePredicatesProxy::New new DataSharePredicatesProxy error."); + return nullptr; + } proxy->predicates_ = std::make_shared(); napi_status ret = napi_wrap(env, thiz, proxy, DataSharePredicatesProxy::Destructor, nullptr, nullptr); if (ret != napi_ok) { diff --git a/data_share/frameworks/js/napi/common/src/datashare_result_set_proxy.cpp b/data_share/frameworks/js/napi/common/src/datashare_result_set_proxy.cpp index 07702427..cab484ad 100644 --- a/data_share/frameworks/js/napi/common/src/datashare_result_set_proxy.cpp +++ b/data_share/frameworks/js/napi/common/src/datashare_result_set_proxy.cpp @@ -106,7 +106,11 @@ napi_value DataShareResultSetProxy::Initialize(napi_env env, napi_callback_info { napi_value self = nullptr; NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &self, nullptr)); - auto *proxy = new DataShareResultSetProxy(); + auto *proxy = new (std::nothrow) DataShareResultSetProxy(); + if (proxy == nullptr) { + LOG_ERROR("DataShareResultSetProxy::Initialize new DataShareResultSetProxy error."); + return nullptr; + } auto finalize = [](napi_env env, void *data, void *hint) { DataShareResultSetProxy *proxy = reinterpret_cast(data); if (proxy != nullptr) { diff --git a/data_share/frameworks/js/napi/dataShare/BUILD.gn b/data_share/frameworks/js/napi/dataShare/BUILD.gn index 04925420..63ac72cc 100644 --- a/data_share/frameworks/js/napi/dataShare/BUILD.gn +++ b/data_share/frameworks/js/napi/dataShare/BUILD.gn @@ -24,6 +24,7 @@ ohos_shared_library("datashare") { sources = [ "${datashare_napi_path}/dataShare/src/async_call.cpp", "${datashare_napi_path}/dataShare/src/napi_datashare_helper.cpp", + "${datashare_napi_path}/dataShare/src/napi_datashare_inner_observer.cpp", "${datashare_napi_path}/dataShare/src/napi_datashare_observer.cpp", "${datashare_napi_path}/dataShare/src/native_datashare_module.cpp", ] @@ -42,6 +43,7 @@ ohos_shared_library("datashare") { "ability_runtime:abilitykit_native", "ability_runtime:napi_base_context", "c_utils:utils", + "common_event_service:cesfwk_innerkits", "data_share:datashare_common", "data_share:datashare_consumer", "hiviewdfx_hilog_native:libhilog", diff --git a/datamgr_service/services/distributeddataservice/framework/store/cursor.cpp b/data_share/frameworks/js/napi/dataShare/include/napi_datashare_inner_observer.h similarity index 40% rename from datamgr_service/services/distributeddataservice/framework/store/cursor.cpp rename to data_share/frameworks/js/napi/dataShare/include/napi_datashare_inner_observer.h index 3ac0d6dc..f38e63c0 100644 --- a/datamgr_service/services/distributeddataservice/framework/store/cursor.cpp +++ b/data_share/frameworks/js/napi/dataShare/include/napi_datashare_inner_observer.h @@ -13,4 +13,35 @@ * limitations under the License. */ -#include "store/cursor.h" +#ifndef NAPI_DATASHARE_INNER_OBSERVER_H +#define NAPI_DATASHARE_INNER_OBSERVER_H + +#include + +#include "napi/native_common.h" +#include "napi/native_api.h" +#include "napi/native_node_api.h" + +namespace OHOS { +namespace DataShare { +class NAPIInnerObserver : public std::enable_shared_from_this { +public: + NAPIInnerObserver(napi_env env, napi_value callback); + void OnChange(); + void DeleteReference(); + napi_ref GetCallback(); +private: + static void OnComplete(uv_work_t *work, int status); + struct ObserverWorker { + std::weak_ptr observer_; + ObserverWorker(std::shared_ptr observerIn) + : observer_(observerIn) {} + }; + + napi_env env_ = nullptr; + napi_ref ref_ = nullptr; + uv_loop_s *loop_ = nullptr; +}; +} // namespace DataShare +} // namespace OHOS +#endif //NAPI_DATASHARE_INNER_OBSERVER_H \ No newline at end of file diff --git a/data_share/frameworks/js/napi/dataShare/include/napi_datashare_observer.h b/data_share/frameworks/js/napi/dataShare/include/napi_datashare_observer.h index ae88f036..fb0ac072 100644 --- a/data_share/frameworks/js/napi/dataShare/include/napi_datashare_observer.h +++ b/data_share/frameworks/js/napi/dataShare/include/napi_datashare_observer.h @@ -16,30 +16,17 @@ #ifndef NAPI_DATASHARE_OBSERVER_H #define NAPI_DATASHARE_OBSERVER_H -#include #include "data_ability_observer_stub.h" -#include "napi/native_common.h" -#include "napi/native_api.h" -#include "napi/native_node_api.h" +#include "napi_datashare_inner_observer.h" namespace OHOS { namespace DataShare { class NAPIDataShareObserver : public AAFwk::DataAbilityObserverStub { public: - NAPIDataShareObserver(napi_env env, napi_value callback); + explicit NAPIDataShareObserver(const std::shared_ptr observer) : observer_(observer){}; virtual ~NAPIDataShareObserver(); void OnChange() override; - void DeleteReference(); - napi_ref GetCallback(); -private: - struct ObserverWorker { - const NAPIDataShareObserver *observer_ = nullptr; - ObserverWorker(const NAPIDataShareObserver *observerIn) : observer_(observerIn) {} - }; - - napi_env env_ = nullptr; - napi_ref ref_ = nullptr; - uv_loop_s *loop_ = nullptr; + std::shared_ptr observer_ = nullptr; }; } // namespace DataShare } // namespace OHOS diff --git a/data_share/frameworks/js/napi/dataShare/src/async_call.cpp b/data_share/frameworks/js/napi/dataShare/src/async_call.cpp index f55ab910..7ce19f08 100644 --- a/data_share/frameworks/js/napi/dataShare/src/async_call.cpp +++ b/data_share/frameworks/js/napi/dataShare/src/async_call.cpp @@ -152,7 +152,7 @@ void AsyncCall::DeleteContext(napi_env env, AsyncContext *context) napi_delete_reference(env, context->self); napi_delete_async_work(env, context->work); } - if (context != nullptr) { + if (context != nullptr && context->ctx != nullptr) { context->ctx->exec_ = nullptr; context->ctx->input_ = nullptr; context->ctx->output_ = nullptr; diff --git a/data_share/frameworks/js/napi/dataShare/src/napi_datashare_helper.cpp b/data_share/frameworks/js/napi/dataShare/src/napi_datashare_helper.cpp index 1a4586ee..59b76a7e 100644 --- a/data_share/frameworks/js/napi/dataShare/src/napi_datashare_helper.cpp +++ b/data_share/frameworks/js/napi/dataShare/src/napi_datashare_helper.cpp @@ -192,10 +192,14 @@ napi_value NapiDataShareHelper::Initialize(napi_env env, napi_callback_info info LOG_ERROR("Parameters error, need at least 2 parameters!"); return nullptr; } - auto *proxy = new NapiDataShareHelper(); + auto *proxy = new (std::nothrow) NapiDataShareHelper(); + if (proxy == nullptr) { + return nullptr; + } auto finalize = [](napi_env env, void * data, void * hint) { NapiDataShareHelper *proxy = reinterpret_cast(data); delete proxy; + LOG_INFO("NapiDataShareHelper has been deleted successfully!"); }; if (napi_wrap(env, self, proxy, finalize, nullptr, nullptr) != napi_ok) { finalize(env, proxy, nullptr); @@ -700,7 +704,7 @@ bool NapiDataShareHelper::HasRegisteredObserver(napi_env env, std::listGetCallback())) { + if (DataShareJSUtils::Equals(env, callback, it->observer_->GetCallback())) { LOG_DEBUG("The observer has already subscribed."); return true; } @@ -718,7 +722,8 @@ void NapiDataShareHelper::RegisteredObserver(napi_env env, const std::string &ur LOG_DEBUG("has registered observer"); return; } - sptr observer(new (std::nothrow) NAPIDataShareObserver(env, callback)); + auto innerObserver = std::make_shared(env, callback); + sptr observer(new (std::nothrow) NAPIDataShareObserver(innerObserver)); if (observer == nullptr) { LOG_ERROR("observer is nullptr"); return; @@ -738,12 +743,12 @@ void NapiDataShareHelper::UnRegisteredObserver(napi_env env, const std::string & auto &list = obs->second; auto it = list.begin(); while (it != list.end()) { - if (!DataShareJSUtils::Equals(env, callback, (*it)->GetCallback())) { + if (!DataShareJSUtils::Equals(env, callback, (*it)->observer_->GetCallback())) { ++it; continue; } datashareHelper_->UnregisterObserver(Uri(uri), *it); - (*it)->DeleteReference(); + (*it)->observer_->DeleteReference(); it = list.erase(it); break; } @@ -764,7 +769,7 @@ void NapiDataShareHelper::UnRegisteredObserver(napi_env env, const std::string & auto it = list.begin(); while (it != list.end()) { datashareHelper_->UnregisterObserver(Uri(uri), *it); - (*it)->DeleteReference(); + (*it)->observer_->DeleteReference(); it = list.erase(it); } observerMap_.erase(uri); diff --git a/data_share/frameworks/js/napi/dataShare/src/napi_datashare_inner_observer.cpp b/data_share/frameworks/js/napi/dataShare/src/napi_datashare_inner_observer.cpp new file mode 100644 index 00000000..c2a21b3b --- /dev/null +++ b/data_share/frameworks/js/napi/dataShare/src/napi_datashare_inner_observer.cpp @@ -0,0 +1,100 @@ +/* + * 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. + */ + +#include "napi_datashare_observer.h" + +#include +#include "datashare_log.h" + +namespace OHOS { +namespace DataShare { +NAPIInnerObserver::NAPIInnerObserver(napi_env env, napi_value callback) + : env_(env) +{ + napi_create_reference(env, callback, 1, &ref_); + napi_get_uv_event_loop(env, &loop_); +} + +void NAPIInnerObserver::OnComplete(uv_work_t *work, int status) +{ + LOG_DEBUG("uv_queue_work start"); + std::shared_ptr innerWorker(reinterpret_cast(work->data)); + auto observer = innerWorker->observer_.lock(); + if (observer == nullptr || observer->ref_ == nullptr) { + delete work; + LOG_ERROR("innerWorker->observer_->ref_ is nullptr"); + return; + } + napi_handle_scope scope = nullptr; + napi_open_handle_scope(observer->env_, &scope); + if (scope == nullptr) { + delete work; + return; + } + napi_value callback = nullptr; + napi_value args[2] = {0}; + napi_value global = nullptr; + napi_value result; + napi_get_reference_value(observer->env_, observer->ref_, &callback); + napi_get_global(observer->env_, &global); + napi_status callStatus = napi_call_function(observer->env_, global, callback, 2, args, &result); + napi_close_handle_scope(observer->env_, scope); + if (callStatus != napi_ok) { + LOG_ERROR("napi_call_function failed status : %{public}d", callStatus); + } + delete work; +} + +void NAPIInnerObserver::OnChange() +{ + LOG_DEBUG("NAPIInnerObserver Start"); + if (ref_ == nullptr) { + LOG_ERROR("ref_ is nullptr"); + return; + } + ObserverWorker *observerWorker = new (std::nothrow)ObserverWorker(shared_from_this()); + if (observerWorker == nullptr) { + LOG_ERROR("Failed to create observerWorker"); + return; + } + uv_work_t *work = new (std::nothrow)uv_work_t(); + if (work == nullptr) { + delete observerWorker; + LOG_ERROR("Failed to create uv work"); + return; + } + work->data = observerWorker; + int ret = uv_queue_work(loop_, work, [](uv_work_t *work) {}, NAPIInnerObserver::OnComplete); + if (ret != 0) { + LOG_ERROR("uv_queue_work failed"); + delete observerWorker; + delete work; + } +} + +void NAPIInnerObserver::DeleteReference() +{ + if (ref_ != nullptr) { + napi_delete_reference(env_, ref_); + ref_ = nullptr; + } +} + +napi_ref NAPIInnerObserver::GetCallback() +{ + return ref_; +} +} // namespace DataShare +} // namespace OHOS \ No newline at end of file diff --git a/data_share/frameworks/js/napi/dataShare/src/napi_datashare_observer.cpp b/data_share/frameworks/js/napi/dataShare/src/napi_datashare_observer.cpp index 0b6df0d0..997cf479 100644 --- a/data_share/frameworks/js/napi/dataShare/src/napi_datashare_observer.cpp +++ b/data_share/frameworks/js/napi/dataShare/src/napi_datashare_observer.cpp @@ -19,82 +19,12 @@ namespace OHOS { namespace DataShare { -NAPIDataShareObserver::NAPIDataShareObserver(napi_env env, napi_value callback) - : env_(env) -{ - napi_create_reference(env, callback, 1, &ref_); - napi_get_uv_event_loop(env, &loop_); -} - NAPIDataShareObserver::~NAPIDataShareObserver() {} void NAPIDataShareObserver::OnChange() { - LOG_DEBUG("Start"); - if (ref_ == nullptr) { - LOG_ERROR("ref_ is nullptr"); - return; - } - ObserverWorker *observerWorker = new (std::nothrow)ObserverWorker(this); - if (observerWorker == nullptr) { - LOG_ERROR("Failed to create observerWorker"); - return; - } - uv_work_t *work = new (std::nothrow)uv_work_t(); - if (work == nullptr) { - delete observerWorker; - LOG_ERROR("Failed to create uv work"); - return; - } - work->data = observerWorker; - int ret = uv_queue_work(loop_, work, - [](uv_work_t *work) {}, - [](uv_work_t *work, int status) { - LOG_DEBUG("uv_queue_work start"); - std::shared_ptr innerWorker(reinterpret_cast(work->data)); - if (innerWorker->observer_->ref_ == nullptr) { - delete work; - LOG_ERROR("innerWorker->observer_->ref_ is nullptr"); - return; - } - napi_handle_scope scope = nullptr; - napi_open_handle_scope(innerWorker->observer_->env_, &scope); - if (scope == nullptr) { - return; - } - napi_value callback = nullptr; - napi_value args[2] = {0}; - napi_value global = nullptr; - napi_value result; - napi_get_reference_value(innerWorker->observer_->env_, - innerWorker->observer_->ref_, &callback); - napi_get_global(innerWorker->observer_->env_, &global); - napi_status callStatus = - napi_call_function(innerWorker->observer_->env_, global, callback, 2, args, &result); - napi_close_handle_scope(innerWorker->observer_->env_, scope); - if (callStatus != napi_ok) { - LOG_ERROR("napi_call_function failed status : %{public}d", callStatus); - } - delete work; - }); - if (ret != 0) { - LOG_ERROR("uv_queue_work failed"); - delete observerWorker; - delete work; - } -} - -void NAPIDataShareObserver::DeleteReference() -{ - if (ref_ != nullptr) { - napi_delete_reference(env_, ref_); - ref_ = nullptr; - } -} - -napi_ref NAPIDataShareObserver::GetCallback() -{ - return ref_; + LOG_DEBUG("NAPIDataShareObserver Start"); + observer_->OnChange(); } } // namespace DataShare } // namespace OHOS diff --git a/data_share/frameworks/js/napi/datashare_ext_ability/datashare_ext_ability.js b/data_share/frameworks/js/napi/datashare_ext_ability/datashare_ext_ability.js index f8204f45..7e4f2aff 100644 --- a/data_share/frameworks/js/napi/datashare_ext_ability/datashare_ext_ability.js +++ b/data_share/frameworks/js/napi/datashare_ext_ability/datashare_ext_ability.js @@ -14,53 +14,53 @@ */ class DataShareExtensionAbility { - onCreate(want, callback) { - console.log('onCreate, want:' + want.abilityName); - } + onCreate(want, callback) { + console.log('onCreate, want:' + want.abilityName); + } - getFileTypes(uri, mimeTypeFilter, callback) { - console.log('getFileTypes, uri:' + uri); - } + getFileTypes(uri, mimeTypeFilter, callback) { + console.log('getFileTypes, uri:' + uri); + } - openFile(uri, mode, callback) { - console.log('openFile, uri:' + uri); - } + openFile(uri, mode, callback) { + console.log('openFile, uri:' + uri); + } - openRawFile(uri, mode, callback) { - console.log('openRawFile, uri:' + uri); - } + openRawFile(uri, mode, callback) { + console.log('openRawFile, uri:' + uri); + } - insert(uri, value, callback) { - console.log('insert, uri:' + uri); - } + insert(uri, value, callback) { + console.log('insert, uri:' + uri); + } - update(uri, predicates, value, callback) { - console.log('update, uri:' + uri); - } + update(uri, predicates, value, callback) { + console.log('update, uri:' + uri); + } - delete(uri, predicates, callback) { - console.log('delete, uri:' + uri); - } + delete(uri, predicates, callback) { + console.log('delete, uri:' + uri); + } - query(uri, predicates, columns, callback) { - console.log('query, uri:' + uri); - } + query(uri, predicates, columns, callback) { + console.log('query, uri:' + uri); + } - getType(uri, callback) { - console.log('getType, uri:' + uri); - } + getType(uri, callback) { + console.log('getType, uri:' + uri); + } - batchInsert(uri, values, callback) { - console.log('batchInsert, uri:' + uri); - } + batchInsert(uri, values, callback) { + console.log('batchInsert, uri:' + uri); + } - normalizeUri(uri, callback) { - console.log('normalizeUri, uri:' + uri); - } + normalizeUri(uri, callback) { + console.log('normalizeUri, uri:' + uri); + } - denormalizeUri(uri, callback) { - console.log('denormalizeUri, uri:' + uri); - } + denormalizeUri(uri, callback) { + console.log('denormalizeUri, uri:' + uri); + } } -export default DataShareExtensionAbility \ No newline at end of file +export default DataShareExtensionAbility; \ No newline at end of file diff --git a/data_share/frameworks/js/napi/datashare_ext_ability_context/datashare_ext_ability_context.js b/data_share/frameworks/js/napi/datashare_ext_ability_context/datashare_ext_ability_context.js index 68ddf9c8..268a766d 100644 --- a/data_share/frameworks/js/napi/datashare_ext_ability_context/datashare_ext_ability_context.js +++ b/data_share/frameworks/js/napi/datashare_ext_ability_context/datashare_ext_ability_context.js @@ -13,12 +13,12 @@ * limitations under the License. */ -var ExtensionContext = requireNapi("application.ExtensionContext") +let ExtensionContext = requireNapi('application.ExtensionContext'); class DataShareExtensionAbilityContext extends ExtensionContext { - constructor(obj) { - super(obj); - } + constructor(obj) { + super(obj); + } } -export default DataShareExtensionAbilityContext \ No newline at end of file +export default DataShareExtensionAbilityContext; \ No newline at end of file diff --git a/data_share/frameworks/native/common/include/adaptor.h b/data_share/frameworks/native/common/include/adaptor.h index 074ac634..8f9b2290 100644 --- a/data_share/frameworks/native/common/include/adaptor.h +++ b/data_share/frameworks/native/common/include/adaptor.h @@ -25,7 +25,7 @@ #else #include "hitrace.h" -#define DISTRIBUTED_DATA_HITRACE(trace) HiTrace hitrace(trace) +#define DISTRIBUTED_DATA_HITRACE(trace) DO_NOTHING #endif diff --git a/data_share/frameworks/native/common/src/ishared_result_set_proxy.cpp b/data_share/frameworks/native/common/src/ishared_result_set_proxy.cpp index 91e58cc5..2df45f5e 100644 --- a/data_share/frameworks/native/common/src/ishared_result_set_proxy.cpp +++ b/data_share/frameworks/native/common/src/ishared_result_set_proxy.cpp @@ -15,7 +15,6 @@ #include "ishared_result_set_proxy.h" -#include "adaptor.h" #include "datashare_errno.h" #include "datashare_log.h" #include "iremote_proxy.h" @@ -74,7 +73,6 @@ int ISharedResultSetProxy::GetAllColumnNames(std::vector &columnNam int ISharedResultSetProxy::GetRowCount(int &count) { - DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__)); if (rowCount_ >= 0) { count = rowCount_; return E_OK; diff --git a/data_share/frameworks/native/consumer/include/base_connection.h b/data_share/frameworks/native/consumer/include/base_connection.h index 97fc66e3..4a77c746 100644 --- a/data_share/frameworks/native/consumer/include/base_connection.h +++ b/data_share/frameworks/native/consumer/include/base_connection.h @@ -32,10 +32,9 @@ enum class ConnectionType { class BaseConnection { public: BaseConnection(ConnectionType type = ConnectionType::NORMAL) : type_(type) {}; - ~BaseConnection()=default; + virtual ~BaseConnection() = default; virtual std::shared_ptr GetDataShareProxy() = 0; - virtual bool ConnectDataShare(const Uri &uri, const sptr token) = 0; - virtual bool IsConnected() = 0; + virtual bool ConnectDataShare(const Uri &uri, const sptr &token) = 0; ConnectionType GetType() { return type_; @@ -43,7 +42,6 @@ public: private: ConnectionType type_ = ConnectionType::NORMAL; }; - }} #endif // DATA_SHARE_BASE_CONNECTION_H diff --git a/data_share/frameworks/native/consumer/include/datashare_connection.h b/data_share/frameworks/native/consumer/include/datashare_connection.h index 02dd7581..e1993281 100644 --- a/data_share/frameworks/native/consumer/include/datashare_connection.h +++ b/data_share/frameworks/native/consumer/include/datashare_connection.h @@ -57,30 +57,24 @@ public: void OnAbilityDisconnectDone(const AppExecFwk::ElementName &element, int resultCode) override; /** - * @brief connect remote ability of DataShareExtAbility. + * @brief disconnect remote ability of DataShareExtAbility. */ - bool ConnectDataShareExtAbility(const Uri &uri, const sptr token); + void DisconnectDataShareExtAbility(); /** * @brief get the proxy of datashare extension ability. * * @return the proxy of datashare extension ability. */ - + std::shared_ptr GetDataShareProxy() override; + bool ConnectDataShare(const Uri &uri, const sptr &token) override ; +private: struct ConnectCondition { std::condition_variable condition; std::mutex mutex; }; - - std::shared_ptr GetDataShareProxy() override; - bool ConnectDataShare(const Uri &uri, const sptr token) override ; - bool IsConnected() override ; - -private: - void DisconnectDataShareExtAbility(); void SetDataShareProxy(sptr proxy); - bool IsExtAbilityConnected(); - + bool ConnectDataShareExtAbility(const Uri &uri, const sptr &token); std::mutex mutex_; std::shared_ptr dataShareProxy_; ConnectCondition condition_; diff --git a/data_share/frameworks/native/consumer/src/connection_factory.cpp b/data_share/frameworks/native/consumer/src/connection_factory.cpp index 4aaca906..2576f1a4 100644 --- a/data_share/frameworks/native/consumer/src/connection_factory.cpp +++ b/data_share/frameworks/native/consumer/src/connection_factory.cpp @@ -12,7 +12,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - + #include "connection_factory.h" #include @@ -34,8 +34,9 @@ std::shared_ptr ConnectionFactory::GetConnection(Uri &uri, cons LOG_ERROR("Factory Create DataShareConnection failed."); return nullptr; } - return std::shared_ptr( - connection.GetRefPtr(), [holder = connection](const auto *) {}); + return std::shared_ptr(connection.GetRefPtr(), [holder = connection](const auto *) { + holder->DisconnectDataShareExtAbility(); + }); } ConnectionFactory& ConnectionFactory::GetInstance() diff --git a/data_share/frameworks/native/consumer/src/datashare_connection.cpp b/data_share/frameworks/native/consumer/src/datashare_connection.cpp index aa0e323b..58e11e2d 100644 --- a/data_share/frameworks/native/consumer/src/datashare_connection.cpp +++ b/data_share/frameworks/native/consumer/src/datashare_connection.cpp @@ -22,8 +22,7 @@ namespace OHOS { namespace DataShare { using namespace AppExecFwk; -constexpr int WAIT_TIME = 3; - +constexpr int WAIT_TIME = 1; /** * @brief This method is called back to receive the connection result after an ability calls the * ConnectAbility method to connect it to an extension ability. @@ -36,6 +35,7 @@ constexpr int WAIT_TIME = 3; void DataShareConnection::OnAbilityConnectDone( const AppExecFwk::ElementName &element, const sptr &remoteObject, int resultCode) { + LOG_INFO("on connect done, uri:%{public}s, ret=%{public}d", uri_.ToString().c_str(), resultCode); if (remoteObject == nullptr) { LOG_ERROR("remote is nullptr"); return; @@ -56,13 +56,13 @@ void DataShareConnection::OnAbilityConnectDone( */ void DataShareConnection::OnAbilityDisconnectDone(const AppExecFwk::ElementName &element, int resultCode) { + LOG_INFO("on disconnect done, uri:%{public}s, ret:%{public}d", uri_.ToString().c_str(), resultCode); { std::unique_lock lock(condition_.mutex); SetDataShareProxy(nullptr); condition_.condition.notify_all(); } if (!uri_.ToString().empty()) { - LOG_INFO("uri : %{public}s disconnect,start reconnect", uri_.ToString().c_str()); ConnectDataShareExtAbility(uri_, token_); } } @@ -70,7 +70,7 @@ void DataShareConnection::OnAbilityDisconnectDone(const AppExecFwk::ElementName /** * @brief connect remote ability of DataShareExtAbility. */ -bool DataShareConnection::ConnectDataShareExtAbility(const Uri &uri, const sptr token) +bool DataShareConnection::ConnectDataShareExtAbility(const Uri &uri, const sptr &token) { if (dataShareProxy_ != nullptr) { return true; @@ -82,17 +82,16 @@ bool DataShareConnection::ConnectDataShareExtAbility(const Uri &uri, const sptr< } else { want.SetUri(uri_); } - std::unique_lock lock(condition_.mutex); ErrCode ret = AAFwk::AbilityManagerClient::GetInstance()->ConnectAbility(want, this, token); if (ret != ERR_OK) { LOG_ERROR("connect ability failed, ret = %{public}d", ret); return false; } + std::unique_lock lock(condition_.mutex); if (condition_.condition.wait_for(lock, std::chrono::seconds(WAIT_TIME), [this] { return dataShareProxy_ != nullptr; })) { LOG_INFO("connect ability ended successfully"); } - LOG_INFO("called end, ret=%{public}d", ret); return dataShareProxy_ != nullptr; } @@ -101,30 +100,22 @@ bool DataShareConnection::ConnectDataShareExtAbility(const Uri &uri, const sptr< */ void DataShareConnection::DisconnectDataShareExtAbility() { + uri_ = Uri(""); if (dataShareProxy_ == nullptr) { return; } - std::unique_lock lock(condition_.mutex); ErrCode ret = AAFwk::AbilityManagerClient::GetInstance()->DisconnectAbility(this); if (ret != ERR_OK) { LOG_ERROR("disconnect ability failed, ret = %{public}d", ret); return; } + std::unique_lock lock(condition_.mutex); if (condition_.condition.wait_for(lock, std::chrono::seconds(WAIT_TIME), [this] { return dataShareProxy_ == nullptr; })) { - LOG_INFO("disconnect ability ended successfully"); + LOG_INFO("disconnect ability successfully"); + } else { + LOG_INFO("disconnect timeout"); } - LOG_INFO("called end, ret=%{public}d", ret); -} - -/** - * @brief check whether connected to remote extension ability. - * - * @return bool true if connected, otherwise false. - */ -bool DataShareConnection::IsExtAbilityConnected() -{ - return dataShareProxy_ != nullptr; } void DataShareConnection::SetDataShareProxy(sptr proxy) @@ -140,22 +131,16 @@ void DataShareConnection::SetDataShareProxy(sptr proxy) DataShareConnection::~DataShareConnection() { - uri_ = Uri(""); - DisconnectDataShareExtAbility(); } + std::shared_ptr DataShareConnection::GetDataShareProxy() { return dataShareProxy_; } -bool DataShareConnection::ConnectDataShare(const Uri & uri, const sptr token) +bool DataShareConnection::ConnectDataShare(const Uri & uri, const sptr &token) { return ConnectDataShareExtAbility(uri, token); } - -bool DataShareConnection::IsConnected() -{ - return dataShareProxy_ != nullptr; -} } // namespace DataShare } // namespace OHOS \ No newline at end of file diff --git a/data_share/frameworks/native/consumer/src/datashare_proxy.cpp b/data_share/frameworks/native/consumer/src/datashare_proxy.cpp index af0a4cc8..fb79f89f 100644 --- a/data_share/frameworks/native/consumer/src/datashare_proxy.cpp +++ b/data_share/frameworks/native/consumer/src/datashare_proxy.cpp @@ -347,7 +347,7 @@ int DataShareProxy::BatchInsert(const Uri &uri, const std::vectorSendRequest(CMD_BATCH_INSERT, data, reply, option); if (err != DATA_SHARE_NO_ERROR) { - LOG_ERROR("GetFileTypes fail to SendRequest. err: %{public}d", err); + LOG_ERROR("fail to SendRequest. err: %{public}d", err); return err == PERMISSION_ERR ? PERMISSION_ERR_CODE : ret; } diff --git a/data_share/frameworks/native/provider/include/datashare_ext_ability.h b/data_share/frameworks/native/provider/include/datashare_ext_ability.h index e4a57eff..dcafee55 100644 --- a/data_share/frameworks/native/provider/include/datashare_ext_ability.h +++ b/data_share/frameworks/native/provider/include/datashare_ext_ability.h @@ -18,6 +18,7 @@ #include #include "extension_base.h" +#include "datashare_business_error.h" #include "datashare_values_bucket.h" #include "datashare_predicates.h" #include "datashare_result_set.h" @@ -138,11 +139,12 @@ public: * @param uri Indicates the path of data to query. * @param predicates Indicates filter criteria. You should define the processing logic when this parameter is null. * @param columns Indicates the columns to query. If this parameter is null, all columns are queried. + * @param businessError Indicates the error by query. * * @return Returns the query result. */ - virtual std::shared_ptr Query( - const Uri &uri, const DataSharePredicates &predicates, std::vector &columns); + virtual std::shared_ptr Query(const Uri &uri, const DataSharePredicates &predicates, + std::vector &columns, DatashareBusinessError &businessError); /** * @brief Obtains the MIME type matching the data specified by the URI of the Data ability. This method should be diff --git a/data_share/frameworks/native/provider/include/js_datashare_ext_ability.h b/data_share/frameworks/native/provider/include/js_datashare_ext_ability.h index 51de22da..41a61e33 100644 --- a/data_share/frameworks/native/provider/include/js_datashare_ext_ability.h +++ b/data_share/frameworks/native/provider/include/js_datashare_ext_ability.h @@ -158,7 +158,7 @@ public: * @return Returns the query result. */ std::shared_ptr Query(const Uri &uri, const DataSharePredicates &predicates, - std::vector &columns) override; + std::vector &columns, DatashareBusinessError &businessError) override; /** * @brief Obtains the MIME type matching the data specified by the URI of the Data ability. This method should be diff --git a/data_share/frameworks/native/provider/src/datashare_ext_ability.cpp b/data_share/frameworks/native/provider/src/datashare_ext_ability.cpp index d4a51eb5..66e6faff 100644 --- a/data_share/frameworks/native/provider/src/datashare_ext_ability.cpp +++ b/data_share/frameworks/native/provider/src/datashare_ext_ability.cpp @@ -95,7 +95,7 @@ int DataShareExtAbility::Delete(const Uri &uri, const DataSharePredicates &predi } std::shared_ptr DataShareExtAbility::Query(const Uri &uri, - const DataSharePredicates &predicates, std::vector &columns) + const DataSharePredicates &predicates, std::vector &columns, DatashareBusinessError &businessError) { return nullptr; } diff --git a/data_share/frameworks/native/provider/src/datashare_stub.cpp b/data_share/frameworks/native/provider/src/datashare_stub.cpp index 7b5682e0..531db554 100644 --- a/data_share/frameworks/native/provider/src/datashare_stub.cpp +++ b/data_share/frameworks/native/provider/src/datashare_stub.cpp @@ -20,6 +20,7 @@ #include "ipc_types.h" #include "ishared_result_set.h" #include "itypes_utils.h" +#include "unistd.h" namespace OHOS { namespace DataShare { @@ -114,8 +115,10 @@ ErrCode DataShareStub::CmdOpenFile(MessageParcel &data, MessageParcel &reply) } if (!reply.WriteFileDescriptor(fd)) { LOG_ERROR("fail to WriteFileDescriptor fd"); + close(fd); return ERR_INVALID_VALUE; } + close(fd); return DATA_SHARE_NO_ERROR; } diff --git a/data_share/frameworks/native/provider/src/datashare_stub_impl.cpp b/data_share/frameworks/native/provider/src/datashare_stub_impl.cpp index 106faf0c..811ce0ba 100644 --- a/data_share/frameworks/native/provider/src/datashare_stub_impl.cpp +++ b/data_share/frameworks/native/provider/src/datashare_stub_impl.cpp @@ -130,6 +130,7 @@ int DataShareStubImpl::Insert(const Uri &uri, const DataShareValuesBucket &value extension->GetResult(ret); return (ret != DEFAULT_NUMBER); }; + std::lock_guard lock(mutex_); uvQueue_->SyncCall(syncTaskFunc, getRetFunc); return ret; } @@ -164,6 +165,7 @@ int DataShareStubImpl::Update(const Uri &uri, const DataSharePredicates &predica extension->GetResult(ret); return (ret != DEFAULT_NUMBER); }; + std::lock_guard lock(mutex_); uvQueue_->SyncCall(syncTaskFunc, getRetFunc); return ret; } @@ -197,6 +199,7 @@ int DataShareStubImpl::Delete(const Uri &uri, const DataSharePredicates &predica extension->GetResult(ret); return (ret != DEFAULT_NUMBER); }; + std::lock_guard lock(mutex_); uvQueue_->SyncCall(syncTaskFunc, getRetFunc); return ret; } @@ -218,8 +221,8 @@ std::shared_ptr DataShareStubImpl::Query(const Uri &uri, return resultSet; } - std::function syncTaskFunc = [=, &columns, &resultSet, &extension]() { - resultSet = extension->Query(uri, predicates, columns); + std::function syncTaskFunc = [=, &columns, &resultSet, &businessError, &extension]() { + resultSet = extension->Query(uri, predicates, columns, businessError); }; std::function getRetFunc = [=, &resultSet, &businessError, client = sptr(this)]() -> bool { @@ -288,6 +291,7 @@ int DataShareStubImpl::BatchInsert(const Uri &uri, const std::vectorGetResult(ret); return (ret != DEFAULT_NUMBER); }; + std::lock_guard lock(mutex_); uvQueue_->SyncCall(syncTaskFunc, getRetFunc); return ret; } diff --git a/data_share/frameworks/native/provider/src/datashare_uv_queue.cpp b/data_share/frameworks/native/provider/src/datashare_uv_queue.cpp index 71374a5e..579620c6 100644 --- a/data_share/frameworks/native/provider/src/datashare_uv_queue.cpp +++ b/data_share/frameworks/native/provider/src/datashare_uv_queue.cpp @@ -91,7 +91,7 @@ void DataShareUvQueue::Purge(uv_work_t* work) LOG_ERROR("invalid work"); return; } - if(work->data == nullptr) { + if (work->data == nullptr) { LOG_ERROR("invalid work->data"); delete work; return; diff --git a/data_share/frameworks/native/provider/src/js_datashare_ext_ability.cpp b/data_share/frameworks/native/provider/src/js_datashare_ext_ability.cpp index c7bd388d..2c6c5072 100644 --- a/data_share/frameworks/native/provider/src/js_datashare_ext_ability.cpp +++ b/data_share/frameworks/native/provider/src/js_datashare_ext_ability.cpp @@ -71,7 +71,8 @@ void JsDataShareExtAbility::Init(const std::shared_ptr &reco HandleScope handleScope(jsRuntime_); auto& engine = jsRuntime_.GetNativeEngine(); - jsObj_ = jsRuntime_.LoadModule(moduleName, srcPath, abilityInfo_->hapPath); + jsObj_ = jsRuntime_.LoadModule(moduleName, srcPath, abilityInfo_->hapPath, + abilityInfo_->compileMode == CompileMode::ES_MODULE); if (jsObj_ == nullptr) { LOG_ERROR("Failed to get jsObj_"); return; @@ -103,9 +104,7 @@ void JsDataShareExtAbility::Init(const std::shared_ptr &reco LOG_ERROR("Failed to get datashare extension ability native object"); return; } - LOG_INFO("Set datashare extension ability context pointer is nullptr: %{public}d", context.get() == nullptr); - nativeObj->SetNativePointer(new std::weak_ptr(context), [](NativeEngine*, void* data, void*) { LOG_INFO("Finalizer for weak_ptr datashare extension ability context is called"); @@ -236,7 +235,11 @@ NativeValue* JsDataShareExtAbility::CallObjectMethod(const char* name, NativeVal } size_t count = argc + 1; - NativeValue **args = new NativeValue *[count]; + NativeValue **args = new (std::nothrow) NativeValue *[count]; + if (args == nullptr) { + LOG_ERROR("JsDataShareExtAbility::CallObjectMethod new NativeValue error."); + return nullptr; + } for (size_t i = 0; i < argc; i++) { args[i] = argv[i]; } @@ -485,10 +488,10 @@ int JsDataShareExtAbility::Delete(const Uri &uri, const DataSharePredicates &pre } std::shared_ptr JsDataShareExtAbility::Query(const Uri &uri, - const DataSharePredicates &predicates, std::vector &columns) + const DataSharePredicates &predicates, std::vector &columns, DatashareBusinessError &businessError) { std::shared_ptr ret; - ret = DataShareExtAbility::Query(uri, predicates, columns); + ret = DataShareExtAbility::Query(uri, predicates, columns, businessError); HandleScope handleScope(jsRuntime_); napi_env env = reinterpret_cast(&jsRuntime_.GetNativeEngine()); diff --git a/data_share/frameworks/native/provider/src/js_datashare_ext_ability_context.cpp b/data_share/frameworks/native/provider/src/js_datashare_ext_ability_context.cpp index aaf10bbd..96c367f3 100644 --- a/data_share/frameworks/native/provider/src/js_datashare_ext_ability_context.cpp +++ b/data_share/frameworks/native/provider/src/js_datashare_ext_ability_context.cpp @@ -60,4 +60,4 @@ NativeValue* CreateJsDataShareExtAbilityContext(NativeEngine& engine, return objValue; } } // namespace DataShare -} // namespace OHOS +} // namespace OHOS \ No newline at end of file diff --git a/data_share/frameworks/native/proxy/include/data_share_manager_impl.h b/data_share/frameworks/native/proxy/include/data_share_manager_impl.h index 9ab3b44c..6a1d3536 100644 --- a/data_share/frameworks/native/proxy/include/data_share_manager_impl.h +++ b/data_share/frameworks/native/proxy/include/data_share_manager_impl.h @@ -37,8 +37,7 @@ public: virtual ~DataShareManagerImpl(); void OnRemoteDied(); std::shared_ptr GetDataShareProxy() override; - bool ConnectDataShare(const Uri &uri, const sptr token) override; - bool IsConnected() override; + bool ConnectDataShare(const Uri &uri, const sptr &token) override; class ServiceDeathRecipient : public IRemoteObject::DeathRecipient { public: diff --git a/data_share/frameworks/native/proxy/src/data_share_manager_impl.cpp b/data_share/frameworks/native/proxy/src/data_share_manager_impl.cpp index e27ec549..d545fd29 100644 --- a/data_share/frameworks/native/proxy/src/data_share_manager_impl.cpp +++ b/data_share/frameworks/native/proxy/src/data_share_manager_impl.cpp @@ -53,6 +53,10 @@ void DataShareManagerImpl::LinkToDeath(const sptr remote) { sptr deathRecipient = new (std::nothrow) DataShareManagerImpl::ServiceDeathRecipient(this); + if (deathRecipient == nullptr) { + LOG_ERROR("DataShareManagerImpl::LinkToDeath new ServiceDeathRecipient error."); + return; + } if (!remote->AddDeathRecipient(deathRecipient)) { LOG_ERROR("add death recipient failed"); } @@ -103,7 +107,7 @@ DataShareManagerImpl::~DataShareManagerImpl() LOG_INFO("destroy"); } -bool DataShareManagerImpl::ConnectDataShare(const Uri &uri, const sptr token) +bool DataShareManagerImpl::ConnectDataShare(const Uri &uri, const sptr &token) { if (dataShareService_ != nullptr) { return true; @@ -121,11 +125,6 @@ bool DataShareManagerImpl::ConnectDataShare(const Uri &uri, const sptr DataShareManagerImpl::GetDataShareProxy() { return dataShareService_; diff --git a/data_share/interfaces/inner_api/BUILD.gn b/data_share/interfaces/inner_api/BUILD.gn index b0074329..464a8ae3 100644 --- a/data_share/interfaces/inner_api/BUILD.gn +++ b/data_share/interfaces/inner_api/BUILD.gn @@ -76,8 +76,9 @@ ohos_shared_library("datashare_consumer") { "ability_runtime:app_context", "ability_runtime:dataobs_manager", "c_utils:utils", + "common_event_service:cesfwk_innerkits", "hiviewdfx_hilog_native:libhilog", - "ipc:ipc_core", + "ipc:ipc_single", "ipc_js:rpc", "napi:ace_napi", "samgr:samgr_proxy", @@ -117,8 +118,9 @@ ohos_shared_library("datashare_provider") { "ability_runtime:runtime", "access_token:libaccesstoken_sdk", "c_utils:utils", + "common_event_service:cesfwk_innerkits", "hiviewdfx_hilog_native:libhilog", - "ipc:ipc_core", + "ipc:ipc_single", "ipc_js:rpc", "napi:ace_napi", ] @@ -144,6 +146,7 @@ ohos_shared_library("datashare_ext_ability_module") { "ability_base:want", "ability_runtime:runtime", "c_utils:utils", + "common_event_service:cesfwk_innerkits", "hiviewdfx_hilog_native:libhilog", ] diff --git a/data_share/interfaces/inner_api/common/include/datashare_predicates.h b/data_share/interfaces/inner_api/common/include/datashare_predicates.h index 7b24e1a9..df8b5eda 100644 --- a/data_share/interfaces/inner_api/common/include/datashare_predicates.h +++ b/data_share/interfaces/inner_api/common/include/datashare_predicates.h @@ -126,7 +126,7 @@ public: } /** - * @brief The LessThanOrEqualTo of the predicate. + * @brief The In of the predicate. * * @param field Indicates the target field. * @param value Indicates the queried value. diff --git a/data_share/test/native/BUILD.gn b/data_share/test/native/BUILD.gn index 41b9a937..8c5ee15a 100644 --- a/data_share/test/native/BUILD.gn +++ b/data_share/test/native/BUILD.gn @@ -146,7 +146,7 @@ ohos_unittest("ErrorCodeTest") { "data_share:datashare_common", "data_share:datashare_consumer", "hilog_native:libhilog", - "ipc:ipc_core", + "ipc:ipc_single", "safwk:system_ability_fwk", "samgr:samgr_proxy", ] diff --git a/data_share/test/native/unittest/mediadatashare_test/src/mediadatashare_unit_test.cpp b/data_share/test/native/unittest/mediadatashare_test/src/mediadatashare_unit_test.cpp index ad447fde..22343851 100644 --- a/data_share/test/native/unittest/mediadatashare_test/src/mediadatashare_unit_test.cpp +++ b/data_share/test/native/unittest/mediadatashare_test/src/mediadatashare_unit_test.cpp @@ -300,7 +300,7 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_Predicates_Test_006, TestSize.Le vector columns; Uri uri(MEDIALIBRARY_DATA_URI); auto resultSet = helper->Query(uri, predicates, columns); - int result = 0; + int result = -1; if (resultSet != nullptr) { resultSet->GetRowCount(result); } diff --git a/datamgr_service/conf/config.json b/datamgr_service/conf/config.json index 91ca003b..2bf2041c 100644 --- a/datamgr_service/conf/config.json +++ b/datamgr_service/conf/config.json @@ -16,6 +16,9 @@ }, { "lib": "libconfigdemo2.z.so" + }, + { + "lib": "libudmf_server.z.so" } ], "bundleChecker": { diff --git a/datamgr_service/services/distributeddataservice/adapter/BUILD.gn b/datamgr_service/services/distributeddataservice/adapter/BUILD.gn index 8f2232af..34abe79d 100644 --- a/datamgr_service/services/distributeddataservice/adapter/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/adapter/BUILD.gn @@ -20,6 +20,7 @@ config("distributeddata_adapter_private_config") { cflags = [ "-Wno-multichar" ] cflags_cc = [ "-fvisibility=hidden" ] + defines = [ "OPENSSL_SUPPRESS_DEPRECATED" ] } config("distributeddata_adapter_public_config") { diff --git a/datamgr_service/services/distributeddataservice/adapter/account/BUILD.gn b/datamgr_service/services/distributeddataservice/adapter/account/BUILD.gn index bf53ea52..11a20558 100644 --- a/datamgr_service/services/distributeddataservice/adapter/account/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/adapter/account/BUILD.gn @@ -59,4 +59,5 @@ ohos_static_library("distributeddata_account_static") { } subsystem_name = "distributeddatamgr" part_name = "datamgr_service" + defines = [ "OPENSSL_SUPPRESS_DEPRECATED" ] } diff --git a/datamgr_service/services/distributeddataservice/adapter/account/test/BUILD.gn b/datamgr_service/services/distributeddataservice/adapter/account/test/BUILD.gn index f0540307..fa8c3d6e 100644 --- a/datamgr_service/services/distributeddataservice/adapter/account/test/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/adapter/account/test/BUILD.gn @@ -41,6 +41,7 @@ ohos_unittest("AccountDelegateTest") { "hiviewdfx_hilog_native:libhilog", "ipc:ipc_core", ] + defines = [ "OPENSSL_SUPPRESS_DEPRECATED" ] } ############################################################################### diff --git a/datamgr_service/services/distributeddataservice/adapter/autils/BUILD.gn b/datamgr_service/services/distributeddataservice/adapter/autils/BUILD.gn index bb40ed87..ad0f6ebe 100644 --- a/datamgr_service/services/distributeddataservice/adapter/autils/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/adapter/autils/BUILD.gn @@ -39,4 +39,5 @@ ohos_static_library("distributeddata_autils_static") { ] subsystem_name = "distributeddatamgr" part_name = "datamgr_service" + defines = [ "OPENSSL_SUPPRESS_DEPRECATED" ] } diff --git a/datamgr_service/services/distributeddataservice/adapter/autils/test/BUILD.gn b/datamgr_service/services/distributeddataservice/adapter/autils/test/BUILD.gn index 283d74b8..afd7c605 100644 --- a/datamgr_service/services/distributeddataservice/adapter/autils/test/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/adapter/autils/test/BUILD.gn @@ -22,6 +22,7 @@ config("module_private_config") { "../../include/autils/", "//foundation/distributeddatamgr/kv_store/frameworks/common", ] + defines = [ "OPENSSL_SUPPRESS_DEPRECATED" ] } ohos_unittest("KvStoreThreadPoolTest") { diff --git a/datamgr_service/services/distributeddataservice/adapter/broadcaster/BUILD.gn b/datamgr_service/services/distributeddataservice/adapter/broadcaster/BUILD.gn index 387aae13..78c9885b 100644 --- a/datamgr_service/services/distributeddataservice/adapter/broadcaster/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/adapter/broadcaster/BUILD.gn @@ -41,4 +41,5 @@ ohos_static_library("distributeddata_broadcaster_static") { ] subsystem_name = "distributeddatamgr" part_name = "datamgr_service" + defines = [ "OPENSSL_SUPPRESS_DEPRECATED" ] } diff --git a/datamgr_service/services/distributeddataservice/adapter/communicator/BUILD.gn b/datamgr_service/services/distributeddataservice/adapter/communicator/BUILD.gn index 05670990..c3e9a4a7 100644 --- a/datamgr_service/services/distributeddataservice/adapter/communicator/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/adapter/communicator/BUILD.gn @@ -63,4 +63,5 @@ ohos_static_library("distributeddata_communicator_static") { subsystem_name = "distributeddatamgr" part_name = "datamgr_service" + defines = [ "OPENSSL_SUPPRESS_DEPRECATED" ] } diff --git a/datamgr_service/services/distributeddataservice/adapter/communicator/src/data_buffer.cpp b/datamgr_service/services/distributeddataservice/adapter/communicator/src/data_buffer.cpp index 7f4060c8..84d2f95a 100644 --- a/datamgr_service/services/distributeddataservice/adapter/communicator/src/data_buffer.cpp +++ b/datamgr_service/services/distributeddataservice/adapter/communicator/src/data_buffer.cpp @@ -40,7 +40,7 @@ DataBuffer::~DataBuffer() bool DataBuffer::Init(size_t size) { - if (buf_ != nullptr) { + if (buf_ != nullptr || size == 0) { return false; } size_ = std::min(size, MAX_DATA_LEN); diff --git a/datamgr_service/services/distributeddataservice/adapter/communicator/src/device_manager_adapter.cpp b/datamgr_service/services/distributeddataservice/adapter/communicator/src/device_manager_adapter.cpp index 5862e35d..d2cafb1f 100644 --- a/datamgr_service/services/distributeddataservice/adapter/communicator/src/device_manager_adapter.cpp +++ b/datamgr_service/services/distributeddataservice/adapter/communicator/src/device_manager_adapter.cpp @@ -311,7 +311,7 @@ void DeviceManagerAdapter::SaveDeviceInfo(const DeviceInfo &dvInfo, const Device DeviceInfo DeviceManagerAdapter::GetLocalDevice() { std::lock_guard lock(devInfoMutex_); - if (!localInfo_.uuid.empty()) { + if (!localInfo_.uuid.empty() && !localInfo_.udid.empty()) { return localInfo_; } @@ -324,7 +324,7 @@ DeviceInfo DeviceManagerAdapter::GetLocalDevice() auto networkId = std::string(info.networkId); auto uuid = GetUuidByNetworkId(networkId); auto udid = GetUdidByNetworkId(networkId); - if (uuid.empty() || udid.empty()) { + if (uuid.empty()) { return {}; } ZLOGI("[LocalDevice] uuid:%{public}s, name:%{public}s, type:%{public}d", @@ -467,4 +467,18 @@ std::string DeviceManagerAdapter::ToNetworkID(const std::string &id) { return GetDeviceInfoFromCache(id).networkId; } + +std::string DeviceManagerAdapter::CalcClientUuid(const std::string &appId, const std::string &uuid) +{ + if (uuid.empty()) { + return ""; + } + std::string encryptedUuid; + auto ret = DeviceManager::GetInstance().GenerateEncryptedUuid(PKG_NAME, uuid, appId, encryptedUuid); + if (ret != DM_OK) { + ZLOGE("failed, result:%{public}d", ret); + return ""; + } + return encryptedUuid; +} } // namespace OHOS::DistributedData diff --git a/datamgr_service/services/distributeddataservice/adapter/communicator/test/BUILD.gn b/datamgr_service/services/distributeddataservice/adapter/communicator/test/BUILD.gn index 318f2192..a3fa43ac 100644 --- a/datamgr_service/services/distributeddataservice/adapter/communicator/test/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/adapter/communicator/test/BUILD.gn @@ -37,6 +37,7 @@ ohos_unittest("CommunicationProviderTest") { "//foundation/distributeddatamgr/datamgr_service/services/distributeddataservice/adapter/communicator:distributeddata_communicator_static", "//third_party/googletest:gtest_main", ] + defines = [ "OPENSSL_SUPPRESS_DEPRECATED" ] } ohos_unittest("DeviceManagerAdapterTest") { @@ -62,6 +63,7 @@ ohos_unittest("DeviceManagerAdapterTest") { "//foundation/distributedhardware/device_manager/interfaces/inner_kits/native_cpp:devicemanagersdk", "//third_party/googletest:gtest_main", ] + defines = [ "OPENSSL_SUPPRESS_DEPRECATED" ] } ############################################################################### diff --git a/datamgr_service/services/distributeddataservice/adapter/dfx/BUILD.gn b/datamgr_service/services/distributeddataservice/adapter/dfx/BUILD.gn index 97d2ebde..bbffd1ac 100644 --- a/datamgr_service/services/distributeddataservice/adapter/dfx/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/adapter/dfx/BUILD.gn @@ -54,4 +54,5 @@ ohos_static_library("distributeddata_dfx_static") { ] subsystem_name = "distributeddatamgr" part_name = "datamgr_service" + defines = [ "OPENSSL_SUPPRESS_DEPRECATED" ] } diff --git a/datamgr_service/services/distributeddataservice/adapter/dfx/test/BUILD.gn b/datamgr_service/services/distributeddataservice/adapter/dfx/test/BUILD.gn index 3ae42016..0c2a6050 100644 --- a/datamgr_service/services/distributeddataservice/adapter/dfx/test/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/adapter/dfx/test/BUILD.gn @@ -52,6 +52,7 @@ ohos_unittest("DistributeddataDfxMSTTest") { "//third_party/googletest:gtest_main", "//third_party/openssl:libcrypto_shared", ] + defines = [ "OPENSSL_SUPPRESS_DEPRECATED" ] } ############################################################################### @@ -109,6 +110,7 @@ ohos_unittest("DistributeddataDfxUTTest") { "//third_party/googletest:gtest_main", "//third_party/openssl:libcrypto_shared", ] + defines = [ "OPENSSL_SUPPRESS_DEPRECATED" ] } ############################################################################### diff --git a/datamgr_service/services/distributeddataservice/adapter/include/communicator/device_manager_adapter.h b/datamgr_service/services/distributeddataservice/adapter/include/communicator/device_manager_adapter.h index 0fc8a548..d4a72a19 100644 --- a/datamgr_service/services/distributeddataservice/adapter/include/communicator/device_manager_adapter.h +++ b/datamgr_service/services/distributeddataservice/adapter/include/communicator/device_manager_adapter.h @@ -39,6 +39,7 @@ public: using AppDeviceChangeListener = OHOS::AppDistributedKv::AppDeviceChangeListener; using Status = OHOS::DistributedKv::Status; static DeviceManagerAdapter &GetInstance(); + void Init(); Status StartWatchDeviceChange(const AppDeviceChangeListener *observer, const PipeInfo &pipeInfo); Status StopWatchDeviceChange(const AppDeviceChangeListener *observer, const PipeInfo &pipeInfo); @@ -47,6 +48,7 @@ public: DeviceInfo GetDeviceInfo(const std::string &id); std::string GetUuidByNetworkId(const std::string &networkId); std::string GetUdidByNetworkId(const std::string &networkId); + std::string CalcClientUuid(const std::string &appId, const std::string &uuid); std::string ToUUID(const std::string &id); std::string ToUDID(const std::string &id); static std::vector ToUUID(const std::vector &devices); diff --git a/datamgr_service/services/distributeddataservice/adapter/permission/BUILD.gn b/datamgr_service/services/distributeddataservice/adapter/permission/BUILD.gn index c6f96a2a..9d63f401 100644 --- a/datamgr_service/services/distributeddataservice/adapter/permission/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/adapter/permission/BUILD.gn @@ -39,4 +39,5 @@ ohos_static_library("distributeddata_permission_static") { ] subsystem_name = "distributeddatamgr" part_name = "datamgr_service" + defines = [ "OPENSSL_SUPPRESS_DEPRECATED" ] } diff --git a/datamgr_service/services/distributeddataservice/adapter/permission/test/BUILD.gn b/datamgr_service/services/distributeddataservice/adapter/permission/test/BUILD.gn index 0c859758..a19f4c30 100644 --- a/datamgr_service/services/distributeddataservice/adapter/permission/test/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/adapter/permission/test/BUILD.gn @@ -43,6 +43,7 @@ ohos_unittest("PermissionValidatorTest") { ] external_deps = [ "hiviewdfx_hilog_native:libhilog" ] + defines = [ "OPENSSL_SUPPRESS_DEPRECATED" ] } group("unittest") { diff --git a/datamgr_service/services/distributeddataservice/adapter/utils/BUILD.gn b/datamgr_service/services/distributeddataservice/adapter/utils/BUILD.gn index cd85ee93..6539b7ab 100644 --- a/datamgr_service/services/distributeddataservice/adapter/utils/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/adapter/utils/BUILD.gn @@ -39,4 +39,5 @@ ohos_static_library("distributeddata_utils_static") { ] subsystem_name = "distributeddatamgr" part_name = "datamgr_service" + defines = [ "OPENSSL_SUPPRESS_DEPRECATED" ] } diff --git a/datamgr_service/services/distributeddataservice/app/BUILD.gn b/datamgr_service/services/distributeddataservice/app/BUILD.gn index 3e962580..48797a85 100644 --- a/datamgr_service/services/distributeddataservice/app/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/app/BUILD.gn @@ -140,4 +140,5 @@ ohos_shared_library("distributeddataservice") { subsystem_name = "distributeddatamgr" part_name = "datamgr_service" + defines = [ "OPENSSL_SUPPRESS_DEPRECATED" ] } diff --git a/datamgr_service/services/distributeddataservice/app/src/checker/BUILD.gn b/datamgr_service/services/distributeddataservice/app/src/checker/BUILD.gn index 6bf706d9..48afce56 100644 --- a/datamgr_service/services/distributeddataservice/app/src/checker/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/app/src/checker/BUILD.gn @@ -46,4 +46,5 @@ ohos_static_library("distributeddata_checker_static") { ] subsystem_name = "distributeddatamgr" part_name = "datamgr_service" + defines = [ "OPENSSL_SUPPRESS_DEPRECATED" ] } diff --git a/datamgr_service/services/distributeddataservice/app/src/flowctrl_manager/BUILD.gn b/datamgr_service/services/distributeddataservice/app/src/flowctrl_manager/BUILD.gn index cf921d03..c17ecd1e 100644 --- a/datamgr_service/services/distributeddataservice/app/src/flowctrl_manager/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/app/src/flowctrl_manager/BUILD.gn @@ -31,4 +31,5 @@ ohos_static_library("distributeddata_flowctrl_static") { subsystem_name = "distributeddatamgr" part_name = "datamgr_service" + defines = [ "OPENSSL_SUPPRESS_DEPRECATED" ] } diff --git a/datamgr_service/services/distributeddataservice/app/src/kvstore_data_service.cpp b/datamgr_service/services/distributeddataservice/app/src/kvstore_data_service.cpp index c9138c65..50bef791 100644 --- a/datamgr_service/services/distributeddataservice/app/src/kvstore_data_service.cpp +++ b/datamgr_service/services/distributeddataservice/app/src/kvstore_data_service.cpp @@ -35,6 +35,7 @@ #include "iservice_registry.h" #include "kvstore_account_observer.h" #include "log_print.h" +#include "metadata/appid_meta_data.h" #include "metadata/meta_data_manager.h" #include "metadata/secret_key_meta_data.h" #include "permission_validator.h" @@ -49,6 +50,7 @@ #include "user_delegate.h" #include "utils/block_integer.h" #include "utils/crypto.h" +#include "upgrade.h" namespace OHOS::DistributedKv { using namespace std::chrono; @@ -57,6 +59,7 @@ using namespace OHOS::DistributedDataDfx; using KvStoreDelegateManager = DistributedDB::KvStoreDelegateManager; using SecretKeyMeta = DistributedData::SecretKeyMetaData; using DmAdapter = DistributedData::DeviceManagerAdapter; +using DBConfig = DistributedDB::RuntimeConfig; REGISTER_SYSTEM_ABILITY_BY_ID(KvStoreDataService, DISTRIBUTED_KV_DATA_SERVICE_ABILITY_ID, true); @@ -97,6 +100,18 @@ void KvStoreDataService::Initialize() AccountDelegate::GetInstance()->Subscribe(accountEventObserver_); deviceInnerListener_ = std::make_unique(*this); DmAdapter::GetInstance().StartWatchDeviceChange(deviceInnerListener_.get(), { "innerListener" }); + auto translateCall = [](const std::string &oriDevId, const DistributedDB::StoreInfo &info) { + StoreMetaData meta; + AppIDMetaData appIdMeta; + MetaDataManager::GetInstance().LoadMeta(info.appId, appIdMeta, true); + meta.bundleName = appIdMeta.bundleName; + meta.storeId = info.storeId; + meta.user = info.userId; + meta.deviceId = oriDevId; + MetaDataManager::GetInstance().LoadMeta(meta.GetKey(), meta); + return Upgrade::GetInstance().GetEncryptedUuidByMeta(meta); + }; + DBConfig::SetTranslateToDeviceIdCallback(translateCall); } sptr KvStoreDataService::GetFeatureInterface(const std::string &name) diff --git a/datamgr_service/services/distributeddataservice/app/src/session_manager/upgrade_manager.cpp b/datamgr_service/services/distributeddataservice/app/src/session_manager/upgrade_manager.cpp index 6550e72a..c3a77e43 100644 --- a/datamgr_service/services/distributeddataservice/app/src/session_manager/upgrade_manager.cpp +++ b/datamgr_service/services/distributeddataservice/app/src/session_manager/upgrade_manager.cpp @@ -51,8 +51,9 @@ void UpgradeManager::Init() CapMetaData UpgradeManager::GetCapability(const std::string &deviceId, bool &status) { status = true; - if (capabilityMap_.Contains(deviceId)) { - return capabilityMap_.Find(deviceId).second; + auto cap = capabilities_.Find(deviceId); + if (cap.first) { + return cap.second; } ZLOGI("load capability from meta"); CapMetaData capMetaData; @@ -60,7 +61,7 @@ CapMetaData UpgradeManager::GetCapability(const std::string &deviceId, bool &sta ZLOGD("cap key:%{public}s", Anonymous::Change(std::string(dbKey.begin(), dbKey.end())).c_str()); status = MetaDataManager::GetInstance().LoadMeta(std::string(dbKey.begin(), dbKey.end()), capMetaData); if (status) { - capabilityMap_.Insert(deviceId, capMetaData); + capabilities_.Insert(deviceId, capMetaData); } ZLOGI("device:%{public}s, version:%{public}d, insert:%{public}d", Anonymous::Change(deviceId).c_str(), capMetaData.version, status); @@ -75,7 +76,7 @@ bool UpgradeManager::InitLocalCapability() auto dbKey = CapMetaRow::GetKeyFor(localDeviceId); bool status = MetaDataManager::GetInstance().SaveMeta({ dbKey.begin(), dbKey.end() }, capMetaData); if (status) { - capabilityMap_.Insert(localDeviceId, capMetaData); + capabilities_.Insert(localDeviceId, capMetaData); } ZLOGI("put capability meta data ret %{public}d", status); return status; diff --git a/datamgr_service/services/distributeddataservice/app/src/session_manager/upgrade_manager.h b/datamgr_service/services/distributeddataservice/app/src/session_manager/upgrade_manager.h index 533aea25..6bb07ea2 100644 --- a/datamgr_service/services/distributeddataservice/app/src/session_manager/upgrade_manager.h +++ b/datamgr_service/services/distributeddataservice/app/src/session_manager/upgrade_manager.h @@ -37,7 +37,7 @@ public: private: bool InitLocalCapability(); - ConcurrentMap capabilityMap_ {}; + ConcurrentMap capabilities_ {}; }; } // namespace OHOS::DistributedData #endif // DISTRIBUTEDDATAMGR_UPGRADE_MANAGER_H diff --git a/datamgr_service/services/distributeddataservice/app/src/uninstaller/BUILD.gn b/datamgr_service/services/distributeddataservice/app/src/uninstaller/BUILD.gn index 030cda89..85a133f2 100644 --- a/datamgr_service/services/distributeddataservice/app/src/uninstaller/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/app/src/uninstaller/BUILD.gn @@ -56,4 +56,5 @@ ohos_static_library("distributeddata_uninstaller_static") { ] subsystem_name = "distributeddatamgr" part_name = "datamgr_service" + defines = [ "OPENSSL_SUPPRESS_DEPRECATED" ] } diff --git a/datamgr_service/services/distributeddataservice/app/src/uninstaller/uninstaller_impl.cpp b/datamgr_service/services/distributeddataservice/app/src/uninstaller/uninstaller_impl.cpp index 2ab4cb22..36f24caf 100644 --- a/datamgr_service/services/distributeddataservice/app/src/uninstaller/uninstaller_impl.cpp +++ b/datamgr_service/services/distributeddataservice/app/src/uninstaller/uninstaller_impl.cpp @@ -18,6 +18,7 @@ #include "uninstaller_impl.h" #include #include +#include "bundle_common_event.h" #include "common_event_manager.h" #include "common_event_support.h" #include "device_manager_adapter.h" @@ -46,7 +47,7 @@ void UninstallEventSubscriber::OnReceiveEvent(const CommonEventData &event) Want want = event.GetWant(); std::string action = want.GetAction(); if (action != CommonEventSupport::COMMON_EVENT_PACKAGE_REMOVED && - action != CommonEventSupport::COMMON_EVENT_SANDBOX_PACKAGE_REMOVED) { + action != OHOS::AppExecFwk::COMMON_EVENT_SANDBOX_PACKAGE_REMOVED) { return; } @@ -82,7 +83,7 @@ Status UninstallerImpl::Init(KvStoreDataService *kvStoreDataService) } MatchingSkills matchingSkills; matchingSkills.AddEvent(CommonEventSupport::COMMON_EVENT_PACKAGE_REMOVED); - matchingSkills.AddEvent(CommonEventSupport::COMMON_EVENT_SANDBOX_PACKAGE_REMOVED); + matchingSkills.AddEvent(OHOS::AppExecFwk::COMMON_EVENT_SANDBOX_PACKAGE_REMOVED); CommonEventSubscribeInfo info(matchingSkills); auto callback = [kvStoreDataService](const std::string &bundleName, int32_t userId, int32_t appIndex) { kvStoreDataService->OnUninstall(bundleName, userId, appIndex, IPCSkeleton::GetCallingTokenID()); diff --git a/datamgr_service/services/distributeddataservice/app/test/BUILD.gn b/datamgr_service/services/distributeddataservice/app/test/BUILD.gn index d081b35a..628ff741 100644 --- a/datamgr_service/services/distributeddataservice/app/test/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/app/test/BUILD.gn @@ -58,6 +58,7 @@ config("module_private_config") { [ "//base/powermgr/power_manager/interfaces/innerkits/native/include" ] } ldflags = [ "-Wl,--whole-archive" ] + defines = [ "OPENSSL_SUPPRESS_DEPRECATED" ] } ohos_unittest("KvStoreDataServiceTest") { @@ -198,64 +199,6 @@ ohos_unittest("KvStoreFlowCtrlManagerTest") { part_name = "datamgr_service" } -ohos_unittest("KvStoreUninstallerTest") { - module_out_path = module_output_path - sources = [ - "../src/dump_helper.cpp", - "../src/feature_stub_impl.cpp", - "../src/kvstore_account_observer.cpp", - "../src/kvstore_data_service.cpp", - "../src/kvstore_device_listener.cpp", - "../src/kvstore_meta_manager.cpp", - "../src/security/security.cpp", - "../src/security/sensitive.cpp", - "../src/session_manager/route_head_handler_impl.cpp", - "../src/session_manager/session_manager.cpp", - "../src/session_manager/upgrade_manager.cpp", - "unittest/uninstaller_test.cpp", - ] - - configs = [ ":module_private_config" ] - - deps = [ - "//foundation/distributeddatamgr/datamgr_service/services/distributeddataservice/adapter:distributeddata_adapter", - "//foundation/distributeddatamgr/datamgr_service/services/distributeddataservice/adapter/broadcaster:distributeddata_broadcaster_static", - "//foundation/distributeddatamgr/datamgr_service/services/distributeddataservice/adapter/utils:distributeddata_utils_static", - "//foundation/distributeddatamgr/datamgr_service/services/distributeddataservice/app/src/checker:distributeddata_checker_static", - "//foundation/distributeddatamgr/datamgr_service/services/distributeddataservice/app/src/flowctrl_manager:distributeddata_flowctrl_static", - "//foundation/distributeddatamgr/datamgr_service/services/distributeddataservice/app/src/uninstaller:distributeddata_uninstaller_static", - "//foundation/distributeddatamgr/datamgr_service/services/distributeddataservice/framework:distributeddatasvcfwk", - "//foundation/distributeddatamgr/datamgr_service/services/distributeddataservice/service:distributeddatasvc", - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb:distributeddb", - "//foundation/distributeddatamgr/kv_store/interfaces/innerkits/distributeddata:distributeddata_inner", - "//third_party/googletest:gtest_main", - ] - - external_deps = [ - "ability_base:base", - "ability_base:want", - "access_token:libaccesstoken_sdk", - "c_utils:utils", - "dataclassification:data_transit_mgr", - "device_auth:deviceauth_sdk", - "hisysevent_native:libhisysevent", - "hitrace_native:hitrace_meter", - "hitrace_native:libhitracechain", - "hiviewdfx_hilog_native:libhilog", - "ipc:ipc_core", - "safwk:system_ability_fwk", - "samgr:samgr_proxy", - ] - - if (datamgr_service_power) { - external_deps += [ - "battery_manager:batterysrv_client", - "power_manager:powermgr_client", - ] - } - part_name = "datamgr_service" -} - ############################################################################### group("unittest") { @@ -265,7 +208,6 @@ group("unittest") { deps += [ ":KvStoreDataServiceTest", ":KvStoreFlowCtrlManagerTest", - ":KvStoreUninstallerTest", ":SessionManagerTest", ] } diff --git a/datamgr_service/services/distributeddataservice/app/test/unittest/session_manager_test.cpp b/datamgr_service/services/distributeddataservice/app/test/unittest/session_manager_test.cpp index 32c00301..0945544a 100644 --- a/datamgr_service/services/distributeddataservice/app/test/unittest/session_manager_test.cpp +++ b/datamgr_service/services/distributeddataservice/app/test/unittest/session_manager_test.cpp @@ -121,7 +121,7 @@ HWTEST_F(SessionManagerTest, PackAndUnPack01, TestSize.Level2) std::vector users; auto recvHandler = RouteHeadHandlerImpl::Create({}); ASSERT_NE(recvHandler, nullptr); - uint32_t parseSize = 0; + uint32_t parseSize = 1; recvHandler->ParseHeadData(data.get(), routeHeadSize, parseSize, users); EXPECT_EQ(routeHeadSize, parseSize); ASSERT_EQ(users.size(), 1); diff --git a/datamgr_service/services/distributeddataservice/framework/BUILD.gn b/datamgr_service/services/distributeddataservice/framework/BUILD.gn index 20b957ba..d22d731b 100644 --- a/datamgr_service/services/distributeddataservice/framework/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/framework/BUILD.gn @@ -68,4 +68,5 @@ ohos_shared_library("distributeddatasvcfwk") { subsystem_name = "distributeddatamgr" part_name = "datamgr_service" + defines = [ "OPENSSL_SUPPRESS_DEPRECATED" ] } diff --git a/datamgr_service/services/distributeddataservice/framework/backuprule/backup_rule_manager.cpp b/datamgr_service/services/distributeddataservice/framework/backuprule/backup_rule_manager.cpp index 2fe05913..d967ad2f 100644 --- a/datamgr_service/services/distributeddataservice/framework/backuprule/backup_rule_manager.cpp +++ b/datamgr_service/services/distributeddataservice/framework/backuprule/backup_rule_manager.cpp @@ -37,11 +37,9 @@ void BackupRuleManager::LoadBackupRules(const std::vector &backupRu void BackupRuleManager::RegisterPlugin(const std::string &backupRule, std::function getter) { - auto it = getters_.Find(backupRule); - if (it.first) { - return; - } - getters_[backupRule] = getter; + getters_.ComputeIfAbsent(backupRule, [&getter](const auto &) mutable { + return std::move(getter); + }); } bool BackupRuleManager::CanBackup() diff --git a/datamgr_service/services/distributeddataservice/framework/checker/checker_manager.cpp b/datamgr_service/services/distributeddataservice/framework/checker/checker_manager.cpp index b7213f3c..8dbc1bb3 100644 --- a/datamgr_service/services/distributeddataservice/framework/checker/checker_manager.cpp +++ b/datamgr_service/services/distributeddataservice/framework/checker/checker_manager.cpp @@ -42,11 +42,9 @@ void CheckerManager::LoadCheckers(std::vector &checkers) void CheckerManager::RegisterPlugin(const std::string &checker, std::function getter) { - auto it = getters_.Find(checker); - if (it.first) { - return; - } - getters_[checker] = getter; + getters_.ComputeIfAbsent(checker, [&getter](const auto &) mutable { + return std::move(getter); + }); } std::string CheckerManager::GetAppId(const StoreInfo &info) diff --git a/datamgr_service/services/distributeddataservice/framework/include/cloud/asset_loader.h b/datamgr_service/services/distributeddataservice/framework/include/cloud/asset_loader.h index c4e9a797..b4cd0d9f 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/cloud/asset_loader.h +++ b/datamgr_service/services/distributeddataservice/framework/include/cloud/asset_loader.h @@ -15,7 +15,7 @@ #ifndef OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_CLOUD_ASSET_LOADER_H #define OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_CLOUD_ASSET_LOADER_H #include -#include "store/asset.h" +#include "store/general_value.h" namespace OHOS::DistributedData { class AssetLoader { public: diff --git a/datamgr_service/services/distributeddataservice/framework/include/metadata/store_meta_data.h b/datamgr_service/services/distributeddataservice/framework/include/metadata/store_meta_data.h index 2a2fcc5f..bb134e35 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/metadata/store_meta_data.h +++ b/datamgr_service/services/distributeddataservice/framework/include/metadata/store_meta_data.h @@ -22,9 +22,10 @@ namespace OHOS::DistributedData { struct API_EXPORT StoreMetaData final : public Serializable { // record meta version for compatible, should update when modify store meta data structure. - static constexpr uint32_t CURRENT_VERSION = 0x03000003; + static constexpr uint32_t CURRENT_VERSION = 0x03000004; // UID -> uid, deviceAccountId -> userId, userId -> user static constexpr uint32_t FIELD_CHANGED_TAG = 0x03000003; + static constexpr uint32_t UUID_CHANGED_TAG = 0x03000004; uint32_t version = CURRENT_VERSION; bool isAutoSync = false; bool isBackup = false; diff --git a/datamgr_service/services/distributeddataservice/framework/include/store/auto_cache.h b/datamgr_service/services/distributeddataservice/framework/include/store/auto_cache.h index 58255f0f..8d86bddb 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/store/auto_cache.h +++ b/datamgr_service/services/distributeddataservice/framework/include/store/auto_cache.h @@ -21,18 +21,19 @@ #include "concurrent_map.h" #include "metadata/store_meta_data.h" #include "store/general_store.h" +#include "store/general_value.h" #include "store/general_watcher.h" -#include "task_scheduler.h" +#include "executor_pool.h" namespace OHOS::DistributedData { class AutoCache { public: - using Error = GeneralStore::ErrorCode; + using Error = GeneralError; using Store = std::shared_ptr; using Watcher = GeneralWatcher; using Watchers = std::set>; using Time = std::chrono::steady_clock::time_point; - using Executor = TaskScheduler; - using TaskId = TaskScheduler::TaskId; + using Executor = ExecutorPool; + using TaskId = ExecutorPool::TaskId; using Creator = std::function; static AutoCache &Instance(); int32_t RegCreator(int32_t type, Creator creator); diff --git a/datamgr_service/services/distributeddataservice/framework/include/store/cursor.h b/datamgr_service/services/distributeddataservice/framework/include/store/cursor.h index e683542d..2ebf8a3e 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/store/cursor.h +++ b/datamgr_service/services/distributeddataservice/framework/include/store/cursor.h @@ -19,15 +19,19 @@ #include #include -#include "store/asset.h" +#include "store/general_value.h" namespace OHOS::DistributedData { class Cursor { public: - using Assets = std::vector; - using Bytes = std::vector; - using Value = std::variant; - using VBucket = std::map; - virtual ~Cursor(){}; + virtual ~Cursor() = default; + + virtual std::string NextCursorTag() const = 0; + + virtual int32_t GetColumnNames(std::vector &names) const = 0; + + virtual int32_t GetColumnName(int32_t col, std::string &name) const = 0; + + virtual int32_t GetColumnType(int32_t col) const = 0; virtual int32_t GetCount() const = 0; @@ -35,19 +39,15 @@ public: virtual int32_t MoveToNext() = 0; - virtual int32_t Close() = 0; + virtual int32_t GetEntry(VBucket &entry) = 0; - virtual int32_t GetEntry(VBucket &entry) const = 0; + virtual int32_t GetRow(VBucket &data) = 0; - virtual int32_t GetColumnNames(std::vector &names) const = 0; + virtual int32_t Get(int32_t col, Value &value) = 0; - virtual int32_t GetColumnName(int32_t col, std::string &name) const = 0; + virtual int32_t Get(const std::string &col, Value &value) = 0; - virtual int32_t GetColumnType(int32_t col) const = 0; - - virtual int32_t Get(int32_t col, Value &value) const = 0; - - virtual int32_t GetRow(VBucket &data) const = 0; + virtual int32_t Close() = 0; }; } // namespace OHOS::DistributedData #endif // OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_STORE_CURSOR_H diff --git a/datamgr_service/services/distributeddataservice/framework/include/store/general_store.h b/datamgr_service/services/distributeddataservice/framework/include/store/general_store.h index 2629480d..f6598661 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/store/general_store.h +++ b/datamgr_service/services/distributeddataservice/framework/include/store/general_store.h @@ -17,26 +17,12 @@ #define OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_STORE_GENERAL_STORE_H #include -#include "store/asset.h" #include "store/cursor.h" +#include "store/general_value.h" #include "store/general_watcher.h" namespace OHOS::DistributedData { class GeneralStore { public: - enum ErrorCode : int32_t { - E_OK = 0, - E_ERROR, - E_BUSY, - E_INVALID_ARGS, - E_NOT_SUPPORT, - E_BUTT, - }; - using Assets = std::vector; - using Bytes = std::vector; - using Value = std::variant; - using Values = std::vector; - using VBucket = std::map; - using VBuckets = std::vector; using Watcher = GeneralWatcher; virtual ~GeneralStore() = default; virtual int32_t Close() = 0; diff --git a/datamgr_service/services/distributeddataservice/framework/include/store/general_value.h b/datamgr_service/services/distributeddataservice/framework/include/store/general_value.h new file mode 100644 index 00000000..58a4547e --- /dev/null +++ b/datamgr_service/services/distributeddataservice/framework/include/store/general_value.h @@ -0,0 +1,93 @@ +/* + * 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_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_STORE_GENERAL_VALUE_H +#define OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_STORE_GENERAL_VALUE_H +#include +#include +#include +#include +#include +namespace OHOS::DistributedData { +enum GeneralError : int32_t +{ + E_OK = 0, + E_ERROR, + E_BUSY, + E_INVALID_ARGS, + E_NOT_INIT, + E_NOT_SUPPORT, + E_ALREADY_CONSUMED, + E_ALREADY_CLOSED, + E_BUTT, +}; +struct Asset { + uint32_t version; + std::string name; + std::string uri; + std::string createTime; + std::string modifyTime; + std::string size; + std::string hash; +}; +using Assets = std::vector; +using Bytes = std::vector; +using Value = std::variant; +using Values = std::vector; +using VBucket = std::map; +using VBuckets = std::vector; +template +inline constexpr size_t TYPE_INDEX = + std::__detail::__variant::__index_of_v; + +template +inline constexpr size_t index_of_v = std::__detail::__variant::__index_of_v<_Tp, _Types...>; + +template +std::enable_if_t<(index_of_v<_T, _Rest...> < sizeof...(_Rest)), const _T *> GetIf(const std::variant<_Rest...> &input) +{ + return std::get_if<_T>(&input); +} + +template +std::enable_if_t<(index_of_v<_T, _Rest...> >= sizeof...(_Rest)), const _T *> GetIf(const std::variant<_Rest...> &input) +{ + return nullptr; +} + +template +bool Get(const _T &input, _O &output) +{ + return false; +} + +template +bool Get(const _T &input, _O &output) +{ + const _First *val = GetIf<_First>(input); + if (val != nullptr) { + output = *val; + return true; + } + return Get<_T, _O, _Rest...>(input, output); +} + +template +bool Convert(const _T &input, std::variant<_Rest...> &output) +{ + return Get<_T, decltype(output), _Rest...>(input, output); +} +} +#endif // OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_STORE_GENERAL_VALUE_H diff --git a/datamgr_service/services/distributeddataservice/framework/include/store/general_watcher.h b/datamgr_service/services/distributeddataservice/framework/include/store/general_watcher.h index 4b8078df..d4c2b32d 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/store/general_watcher.h +++ b/datamgr_service/services/distributeddataservice/framework/include/store/general_watcher.h @@ -16,12 +16,7 @@ #ifndef OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_STORE_GENERAL_WATCHER_H #define OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_STORE_GENERAL_WATCHER_H #include -#include -#include -#include -#include - -#include "store/asset.h" +#include "store/general_value.h" #include "visibility.h" namespace OHOS::DistributedData { class GeneralWatcher { @@ -39,11 +34,6 @@ public: OP_DELETE, OP_BUTT, }; - using Assets = std::vector; - using Bytes = std::vector; - using Value = std::variant; - using Values = std::vector; - using VBucket = std::map; API_EXPORT virtual ~GeneralWatcher() = default; virtual int32_t OnChange(Origin origin, const std::string &id) = 0; virtual int32_t OnChange(Origin origin, const std::string &id, const std::vector &values) = 0; diff --git a/datamgr_service/services/distributeddataservice/framework/store/auto_cache.cpp b/datamgr_service/services/distributeddataservice/framework/store/auto_cache.cpp index 990f1b90..84c768d0 100644 --- a/datamgr_service/services/distributeddataservice/framework/store/auto_cache.cpp +++ b/datamgr_service/services/distributeddataservice/framework/store/auto_cache.cpp @@ -38,8 +38,8 @@ void AutoCache::Bind(std::shared_ptr executor) return; } executor_ = executor; - taskId_ = executor_->Scheduler(std::chrono::steady_clock::now() + std::chrono::minutes(INTERVAL), - std::bind(&AutoCache::GarbageCollect, this, false), std::chrono::minutes(INTERVAL)); + taskId_ = executor_->Schedule(std::bind(&AutoCache::GarbageCollect, this, false), std::chrono::minutes(INTERVAL), + std::chrono::minutes(INTERVAL)); } AutoCache::AutoCache() {} diff --git a/datamgr_service/services/distributeddataservice/framework/test/BUILD.gn b/datamgr_service/services/distributeddataservice/framework/test/BUILD.gn index 006e0bd0..1e2ccfa5 100644 --- a/datamgr_service/services/distributeddataservice/framework/test/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/framework/test/BUILD.gn @@ -24,6 +24,7 @@ config("module_private_config") { "../../service/bootstrap/include/", ] ldflags = [ "-Wl,--whole-archive" ] + defines = [ "OPENSSL_SUPPRESS_DEPRECATED" ] } ohos_unittest("CheckerManagerTest") { diff --git a/datamgr_service/services/distributeddataservice/framework/test/serializable_test.cpp b/datamgr_service/services/distributeddataservice/framework/test/serializable_test.cpp index 55364fd9..95c0154b 100644 --- a/datamgr_service/services/distributeddataservice/framework/test/serializable_test.cpp +++ b/datamgr_service/services/distributeddataservice/framework/test/serializable_test.cpp @@ -13,6 +13,7 @@ * limitations under the License. */ #define LOG_TAG "SerializableTest" +#include #include "log_print.h" #include "serializable/serializable.h" #include "gtest/gtest.h" @@ -112,7 +113,7 @@ public: */ HWTEST_F(SerializableTest, GetNormalVal, TestSize.Level2) { - ZLOGI("SerializableSuite GetVal begin."); + ZLOGI("SerializableSuite GetNormalVal begin."); Normal normal; normal.name = "normal"; normal.count = -1; @@ -135,9 +136,9 @@ HWTEST_F(SerializableTest, GetNormalVal, TestSize.Level2) */ HWTEST_F(SerializableTest, DeleteSerializable, TestSize.Level2) { - ZLOGI("SerializableSuite GetVal begin."); - NormalEx *normalEx = new NormalEx(); - delete normalEx; + ZLOGI("SerializableSuite DeleteSerializable begin."); + ASSERT_FALSE(std::is_destructible::value); + ASSERT_TRUE(std::is_destructible::value); } /** @@ -149,7 +150,7 @@ HWTEST_F(SerializableTest, DeleteSerializable, TestSize.Level2) */ HWTEST_F(SerializableTest, GetMutilVal, TestSize.Level2) { - ZLOGI("SerializableSuite GetVal begin."); + ZLOGI("SerializableSuite GetMutilVal begin."); NormalEx normalEx; normalEx.normals = {Normal()}; normalEx.name = "normalEx"; diff --git a/datamgr_service/services/distributeddataservice/service/BUILD.gn b/datamgr_service/services/distributeddataservice/service/BUILD.gn index 6adf404a..d05b54c5 100644 --- a/datamgr_service/services/distributeddataservice/service/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/service/BUILD.gn @@ -137,4 +137,5 @@ ohos_shared_library("distributeddatasvc") { subsystem_name = "distributeddatamgr" part_name = "datamgr_service" + defines = [ "OPENSSL_SUPPRESS_DEPRECATED" ] } diff --git a/datamgr_service/services/distributeddataservice/service/bootstrap/src/bootstrap.cpp b/datamgr_service/services/distributeddataservice/service/bootstrap/src/bootstrap.cpp index 7d39b94f..96172649 100644 --- a/datamgr_service/services/distributeddataservice/service/bootstrap/src/bootstrap.cpp +++ b/datamgr_service/services/distributeddataservice/service/bootstrap/src/bootstrap.cpp @@ -58,9 +58,12 @@ void Bootstrap::LoadComponents() if (comp.lib.empty()) { continue; } - + char path[PATH_MAX] = { 0 }; + if (realpath(comp.lib.c_str(), path) == NULL) { + continue; + } // no need to close the component, so we don't keep the handles - auto handle = dlopen(comp.lib.c_str(), RTLD_LAZY); + auto handle = dlopen(path, RTLD_LAZY); if (handle == nullptr) { ZLOGE("dlopen(%{public}s) failed(%{public}d)!", comp.lib.c_str(), errno); continue; diff --git a/datamgr_service/services/distributeddataservice/service/data_share/data_share_profile_info.cpp b/datamgr_service/services/distributeddataservice/service/data_share/data_share_profile_info.cpp index 329b9499..da563ec8 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/data_share_profile_info.cpp +++ b/datamgr_service/services/distributeddataservice/service/data_share/data_share_profile_info.cpp @@ -12,7 +12,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - + #define LOG_TAG "DataShareProfileInfo" #include "data_share_profile_info.h" @@ -57,9 +57,7 @@ bool ProfileInfo::Marshal(json &node) const bool ProfileInfo::Unmarshal(const json &node) { - bool ret = true; - ret = GetValue(node, GET_NAME(tableConfig), tableConfig) && ret; - return ret; + return GetValue(node, GET_NAME(tableConfig), tableConfig); } bool DataShareProfileInfo::GetProfileInfoFromExtension(const AppExecFwk::BundleInfo &bundleInfo, @@ -71,15 +69,14 @@ bool DataShareProfileInfo::GetProfileInfoFromExtension(const AppExecFwk::BundleI return true; } - for (auto &item : bundleInfo.extensionInfos) { + for (auto const &item : bundleInfo.extensionInfos) { if (item.type == AppExecFwk::ExtensionAbilityType::DATASHARE) { - std::vector infos; bool isCompressed = !item.hapPath.empty(); std::string resourcePath = isCompressed ? item.hapPath : item.resourcePath; - if (!GetResProfileByMetadata(item.metadata, resourcePath, isCompressed, infos) || infos.empty()) { - ZLOGE("failed, bundleName is %{public}s, resourcePath is %{public}s, metadata.size is %{public}zu," - "infos.size is %{public}zu", bundleInfo.name.c_str(), resourcePath.c_str(), item.metadata.size(), - infos.size()); + std::vector infos = GetResProfileByMetadata(item.metadata, resourcePath, isCompressed); + if (infos.empty()) { + ZLOGE("failed, bundleName is %{public}s, resourcePath is %{public}s, metadata.size is %{public}zu,", + bundleInfo.name.c_str(), resourcePath.c_str(), item.metadata.size()); return false; } return profileInfo.Unmarshall(infos[0]); @@ -89,23 +86,24 @@ bool DataShareProfileInfo::GetProfileInfoFromExtension(const AppExecFwk::BundleI return false; } -bool DataShareProfileInfo::GetResProfileByMetadata(const std::vector &metadata, - const std::string &resourcePath, bool isCompressed, std::vector &profileInfos) const +std::vector DataShareProfileInfo::GetResProfileByMetadata( + const std::vector &metadata, const std::string &resourcePath, bool isCompressed) const { + std::vector profileInfos; if (metadata.empty() || resourcePath.empty()) { - return false; + return profileInfos; } std::shared_ptr resMgr = InitResMgr(resourcePath); if (resMgr == nullptr) { - return false; + return profileInfos; } - for (auto &meta : metadata) { - if (meta.name.compare(DATA_SHARE_PROFILE_META) == 0) { - return GetResFromResMgr(meta.resource, *resMgr, isCompressed, profileInfos); + for (auto const &meta : metadata) { + if (meta.name == DATA_SHARE_PROFILE_META) { + return GetResFromResMgr(meta.resource, *resMgr, isCompressed); } } - return false; + return profileInfos; } std::shared_ptr DataShareProfileInfo::InitResMgr(const std::string &resourcePath) const @@ -128,17 +126,18 @@ std::shared_ptr DataShareProfileInfo::InitResMgr(const std::str return resMgr; } -bool DataShareProfileInfo::GetResFromResMgr(const std::string &resName, ResourceManager &resMgr, - bool isCompressed, std::vector &profileInfos) const +std::vector DataShareProfileInfo::GetResFromResMgr(const std::string &resName, ResourceManager &resMgr, + bool isCompressed) const { + std::vector profileInfos; if (resName.empty()) { - return false; + return profileInfos; } size_t pos = resName.rfind(PROFILE_FILE_PREFIX); if ((pos == std::string::npos) || (pos == resName.length() - PROFILE_PREFIX_LEN)) { ZLOGE("res name invalid, resName is %{public}s", resName.c_str()); - return false; + return profileInfos; } std::string profileName = resName.substr(pos + PROFILE_PREFIX_LEN); // hap is compressed status, get file content. @@ -150,34 +149,34 @@ bool DataShareProfileInfo::GetResFromResMgr(const std::string &resName, Resource if (ret != SUCCESS || fileContent == nullptr) { ZLOGE("failed, ret is %{public}d, profileName is %{public}s", ret, profileName.c_str()); - return false; + return profileInfos; } if (len == 0) { ZLOGE("fileContent is empty, profileName is %{public}s", profileName.c_str()); - return false; + return profileInfos; } std::string rawData(fileContent.get(), fileContent.get() + len); if (!Config::IsJson(rawData)) { ZLOGE("rawData is not json, profileName is %{public}s", profileName.c_str()); - return false; + return profileInfos; } profileInfos.push_back(std::move(rawData)); - return true; + return profileInfos; } // hap is decompressed status, get file path then read file. std::string resPath; RState ret = resMgr.GetProfileByName(profileName.c_str(), resPath); if (ret != SUCCESS) { ZLOGE("profileName not found, ret is %{public}d, profileName is %{public}s", ret, profileName.c_str()); - return false; + return profileInfos; } std::string profile = ReadProfile(resPath); if (profile.empty()) { ZLOGE("Read profile failed, resPath is %{public}s", resPath.c_str()); - return false; + return profileInfos; } profileInfos.push_back(std::move(profile)); - return true; + return profileInfos; } bool DataShareProfileInfo::IsFileExisted(const std::string &filePath) const diff --git a/datamgr_service/services/distributeddataservice/service/data_share/data_share_profile_info.h b/datamgr_service/services/distributeddataservice/service/data_share/data_share_profile_info.h index 9dac5236..b943aaf1 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/data_share_profile_info.h +++ b/datamgr_service/services/distributeddataservice/service/data_share/data_share_profile_info.h @@ -45,11 +45,11 @@ public: ProfileInfo &profileInfo, bool &isSingleApp); private: - bool GetResProfileByMetadata(const std::vector &metadata, const std::string &resourcePath, - bool isCompressed, std::vector &profileInfos) const; + std::vector GetResProfileByMetadata(const std::vector &metadata, + const std::string &resourcePath, bool isCompressed) const; std::shared_ptr InitResMgr(const std::string &basicString) const; - bool GetResFromResMgr(const std::string &resName, ResourceManager &resMgr, bool isCompressed, - std::vector &profileInfos) const; + std::vector GetResFromResMgr(const std::string &resName, ResourceManager &resMgr, + bool isCompressed) const; std::string ReadProfile(const std::string &resPath) const; bool IsFileExisted(const std::string &filePath) const; }; diff --git a/datamgr_service/services/distributeddataservice/service/data_share/data_share_service_impl.cpp b/datamgr_service/services/distributeddataservice/service/data_share/data_share_service_impl.cpp index 63c9fd3f..4fc2ca94 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/data_share_service_impl.cpp +++ b/datamgr_service/services/distributeddataservice/service/data_share/data_share_service_impl.cpp @@ -212,13 +212,12 @@ std::string DataShareServiceImpl::GetRealityTableName(uint32_t tokenId, const Ap PermissionProxy::PermissionState DataShareServiceImpl::VerifyPermission(uint32_t tokenID, DataShareServiceImpl::PermissionType permissionType, const AppExecFwk::BundleInfo &bundleInfo) { - std::string permission; switch (permissionType) { case PermissionType::READ_PERMISSION: { - return PermissionProxy::QueryReadPermission(tokenID, permission, bundleInfo); + return PermissionProxy::QueryReadPermission(tokenID, bundleInfo); } case PermissionType::WRITE_PERMISSION: { - return PermissionProxy::QueryWritePermission(tokenID, permission, bundleInfo); + return PermissionProxy::QueryWritePermission(tokenID, bundleInfo); } } return PermissionProxy::PermissionState::NOT_FIND; diff --git a/datamgr_service/services/distributeddataservice/service/data_share/permission_proxy.cpp b/datamgr_service/services/distributeddataservice/service/data_share/permission_proxy.cpp index 0403006b..ab68c1df 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/permission_proxy.cpp +++ b/datamgr_service/services/distributeddataservice/service/data_share/permission_proxy.cpp @@ -38,17 +38,16 @@ bool PermissionProxy::GetBundleInfo(const std::string &bundleName, uint32_t toke } PermissionProxy::PermissionState PermissionProxy::QueryWritePermission(uint32_t tokenId, - std::string &permission, const AppExecFwk::BundleInfo &bundleInfo) + const AppExecFwk::BundleInfo &bundleInfo) { - for (auto &item : bundleInfo.extensionInfos) { + for (auto const &item : bundleInfo.extensionInfos) { if (item.type == AppExecFwk::ExtensionAbilityType::DATASHARE) { - permission = item.writePermission; - if (permission.empty()) { + if (item.writePermission.empty()) { ZLOGW("WritePermission is empty! BundleName is %{public}s, tokenId is %{public}x", bundleInfo.name.c_str(), tokenId); return PermissionState::NOT_FIND; } - int status = Security::AccessToken::AccessTokenKit::VerifyAccessToken(tokenId, permission); + int status = Security::AccessToken::AccessTokenKit::VerifyAccessToken(tokenId, item.writePermission); if (status != Security::AccessToken::PermissionState::PERMISSION_GRANTED) { ZLOGE("Verify write permission denied!"); return PermissionState::DENIED; @@ -60,16 +59,16 @@ PermissionProxy::PermissionState PermissionProxy::QueryWritePermission(uint32_t } PermissionProxy::PermissionState PermissionProxy::QueryReadPermission(uint32_t tokenId, - std::string &permission, const AppExecFwk::BundleInfo &bundleInfo) + const AppExecFwk::BundleInfo &bundleInfo) { - for (auto &item : bundleInfo.extensionInfos) { + for (auto const &item : bundleInfo.extensionInfos) { if (item.type == AppExecFwk::ExtensionAbilityType::DATASHARE) { if (item.readPermission.empty()) { ZLOGW("ReadPermission is empty! BundleName is %{public}s, tokenId is %{public}x", bundleInfo.name.c_str(), tokenId); return PermissionState::NOT_FIND; } - int status = Security::AccessToken::AccessTokenKit::VerifyAccessToken(tokenId, permission); + int status = Security::AccessToken::AccessTokenKit::VerifyAccessToken(tokenId, item.readPermission); if (status != Security::AccessToken::PermissionState::PERMISSION_GRANTED) { ZLOGE("Verify Read permission denied!"); return PermissionState::DENIED; diff --git a/datamgr_service/services/distributeddataservice/service/data_share/permission_proxy.h b/datamgr_service/services/distributeddataservice/service/data_share/permission_proxy.h index afc4be36..69b6ae0a 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/permission_proxy.h +++ b/datamgr_service/services/distributeddataservice/service/data_share/permission_proxy.h @@ -39,10 +39,8 @@ public: }; static bool GetBundleInfo(const std::string &bundleName, uint32_t tokenId, AppExecFwk::BundleInfo &bundleInfo); - static PermissionState QueryWritePermission(uint32_t tokenId, - std::string &permission, const AppExecFwk::BundleInfo &bundleInfo); - static PermissionState QueryReadPermission(uint32_t tokenId, - std::string &permission, const AppExecFwk::BundleInfo &bundleInfo); + static PermissionState QueryWritePermission(uint32_t tokenId, const AppExecFwk::BundleInfo &bundleInfo); + static PermissionState QueryReadPermission(uint32_t tokenId, const AppExecFwk::BundleInfo &bundleInfo); static bool QueryMetaData(const std::string &bundleName, const std::string &storeName, DistributedData::StoreMetaData &metaData, int32_t userId); static std::string GetTableNameByCrossUserMode(const ProfileInfo &profileInfo, diff --git a/datamgr_service/services/distributeddataservice/service/data_share/rdb_adaptor.h b/datamgr_service/services/distributeddataservice/service/data_share/rdb_adaptor.h index 143d7ae8..f26436ac 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/rdb_adaptor.h +++ b/datamgr_service/services/distributeddataservice/service/data_share/rdb_adaptor.h @@ -34,7 +34,7 @@ using StoreMetaData = OHOS::DistributedData::StoreMetaData; using namespace OHOS::NativeRdb; class RdbDelegate { public: - RdbDelegate(const StoreMetaData &data, int &errCode); + RdbDelegate(const StoreMetaData &meta, int &errCode); virtual ~RdbDelegate(); int64_t Insert(const std::string &tableName, const DataShareValuesBucket &valuesBucket); int64_t Update(const std::string &tableName, const DataSharePredicates &predicate, diff --git a/datamgr_service/services/distributeddataservice/service/data_share/uri_utils.cpp b/datamgr_service/services/distributeddataservice/service/data_share/uri_utils.cpp index 96b41176..b88ae0ac 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/uri_utils.cpp +++ b/datamgr_service/services/distributeddataservice/service/data_share/uri_utils.cpp @@ -31,32 +31,32 @@ bool URIUtils::GetInfoFromURI(const std::string &uri, UriInfo &uriInfo, bool tab return false; } - uriInfo.bundleName = splitUri[URI_INDEX_BUNLDENAME]; - uriInfo.moduleName = splitUri[URI_INDEX_MODULENAME]; - uriInfo.storeName = splitUri[URI_INDEX_STORENAME]; - if (splitUri.size() > URI_INDEX_MIN) { - uriInfo.tableName = splitUri[URI_INDEX_TABLENAME]; + uriInfo.bundleName = splitUri[BUNDLE_NAME]; + uriInfo.moduleName = splitUri[MODULE_NAME]; + uriInfo.storeName = splitUri[STORE_NAME]; + if (splitUri.size() > OPTIONAL_BEGIN) { + uriInfo.tableName = splitUri[TABLE_NAME]; } return true; } bool URIUtils::IsValidPath(const std::vector &splitUri, bool tableNameEmpty) { - if (splitUri.size() < URI_INDEX_MIN) { + if (splitUri.size() < OPTIONAL_BEGIN) { return false; } - if (splitUri[URI_INDEX_BUNLDENAME].empty() || splitUri[URI_INDEX_MODULENAME].empty() || - splitUri[URI_INDEX_STORENAME].empty()) { + if (splitUri[BUNDLE_NAME].empty() || splitUri[MODULE_NAME].empty() || + splitUri[STORE_NAME].empty()) { ZLOGE("Uri has empty field!"); return false; } if (!tableNameEmpty) { - if (splitUri.size() < URI_INDEX_MAX) { + if (splitUri.size() < PARAM_BUTT) { ZLOGE("Uri need contains tableName"); return false; } - if (splitUri[URI_INDEX_TABLENAME].empty()) { + if (splitUri[TABLE_NAME].empty()) { ZLOGE("Uri tableName can't be empty!"); return false; } diff --git a/datamgr_service/services/distributeddataservice/service/data_share/uri_utils.h b/datamgr_service/services/distributeddataservice/service/data_share/uri_utils.h index 625c45a9..659773b2 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/uri_utils.h +++ b/datamgr_service/services/distributeddataservice/service/data_share/uri_utils.h @@ -38,12 +38,14 @@ public: private: static bool IsValidPath(const std::vector &splitUri, bool tableNameEmpty); - static constexpr size_t URI_INDEX_BUNLDENAME = 0; - static constexpr size_t URI_INDEX_MODULENAME = 1; - static constexpr size_t URI_INDEX_STORENAME = 2; - static constexpr size_t URI_INDEX_TABLENAME = 3; - static constexpr size_t URI_INDEX_MIN = 3; - static constexpr size_t URI_INDEX_MAX = 4; + enum PATH_PARAM : int32_t { + BUNDLE_NAME = 0, + MODULE_NAME, + STORE_NAME, + OPTIONAL_BEGIN, + TABLE_NAME = OPTIONAL_BEGIN, + PARAM_BUTT + }; }; } // namespace OHOS::DataShare #endif // DATASHARESERVICE_URI_UTILS_H diff --git a/datamgr_service/services/distributeddataservice/service/directory/src/directory_manager.cpp b/datamgr_service/services/distributeddataservice/service/directory/src/directory_manager.cpp index eba3ef89..bba79049 100644 --- a/datamgr_service/services/distributeddataservice/service/directory/src/directory_manager.cpp +++ b/datamgr_service/services/distributeddataservice/service/directory/src/directory_manager.cpp @@ -208,7 +208,7 @@ std::vector DirectoryManager::GetVersions() { std::vector versions; for (size_t i = 0; i < strategies_.size(); ++i) { - versions[i] = strategies_[i].version; + versions.push_back(strategies_[i].version); } return versions; } diff --git a/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_service_impl.cpp b/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_service_impl.cpp index 6e19c96a..a19acff4 100644 --- a/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_service_impl.cpp +++ b/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_service_impl.cpp @@ -39,7 +39,6 @@ #include "utils/anonymous.h" #include "utils/constant.h" #include "utils/converter.h" -#include "utils/crypto.h" namespace OHOS::DistributedKv { using namespace OHOS::DistributedData; using namespace OHOS::AppDistributedKv; @@ -351,36 +350,6 @@ Status KVDBServiceImpl::GetBackupPassword(const AppId &appId, const StoreId &sto return (BackupManager::GetInstance().GetPassWord(metaData, password)) ? SUCCESS : ERROR; } -KVDBService::DevBrief KVDBServiceImpl::GetLocalDevice() -{ - DevBrief brief; - CheckerManager::StoreInfo storeInfo; - storeInfo.tokenId = IPCSkeleton::GetCallingTokenID(); - storeInfo.uid = IPCSkeleton::GetCallingPid(); - auto appId = CheckerManager::GetInstance().GetAppId(storeInfo); - auto device = DMAdapter::GetInstance().GetLocalDevice(); - brief.networkId = std::move(device.networkId); - brief.uuid = Crypto::Sha256(appId + "_" + device.uuid); - return brief; -} - -std::vector KVDBServiceImpl::GetRemoteDevices() -{ - std::vector briefs; - CheckerManager::StoreInfo storeInfo; - storeInfo.tokenId = IPCSkeleton::GetCallingTokenID(); - storeInfo.uid = IPCSkeleton::GetCallingPid(); - auto appId = CheckerManager::GetInstance().GetAppId(storeInfo); - auto devices = DMAdapter::GetInstance().GetRemoteDevices(); - for (const auto &device : devices) { - DevBrief brief; - brief.networkId = std::move(device.networkId); - brief.uuid = Crypto::Sha256(appId + "_" + device.uuid); - briefs.push_back(std::move(brief)); - } - return briefs; -} - Status KVDBServiceImpl::BeforeCreate(const AppId &appId, const StoreId &storeId, const Options &options) { ZLOGD("appId:%{public}s storeId:%{public}s to export data", appId.appId.c_str(), storeId.storeId.c_str()); diff --git a/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_service_impl.h b/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_service_impl.h index 72dddfc4..3cee4848 100644 --- a/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_service_impl.h +++ b/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_service_impl.h @@ -53,9 +53,7 @@ public: Status Subscribe(const AppId &appId, const StoreId &storeId, sptr observer) override; Status Unsubscribe(const AppId &appId, const StoreId &storeId, sptr observer) override; Status GetBackupPassword(const AppId &appId, const StoreId &storeId, std::vector &password) override; - DevBrief GetLocalDevice() override; - std::vector GetRemoteDevices() override; - + int32_t OnAppExit(pid_t uid, pid_t pid, uint32_t tokenId, const std::string &appId) override; int32_t ResolveAutoLaunch(const std::string &identifier, DBLaunchParam ¶m) override; int32_t OnUserChange(uint32_t code, const std::string &user, const std::string &account) override; diff --git a/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_service_stub.cpp b/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_service_stub.cpp index 95e333dc..61fdde59 100644 --- a/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_service_stub.cpp +++ b/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_service_stub.cpp @@ -40,8 +40,6 @@ const KVDBServiceStub::Handler KVDBServiceStub::HANDLERS[TRANS_BUTT] = { &KVDBServiceStub::OnSubscribe, &KVDBServiceStub::OnUnsubscribe, &KVDBServiceStub::OnGetBackupPassword, - &KVDBServiceStub::OnGetLocalDevice, - &KVDBServiceStub::OnGetRemoteDevices, }; int KVDBServiceStub::OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply) @@ -61,9 +59,6 @@ int KVDBServiceStub::OnRemoteRequest(uint32_t code, MessageParcel &data, Message AppId appId; StoreId storeId; - if (TRANS_NO_APPID_BEGIN <= code && code <= TRANS_NO_APPID_END) { - return (this->*HANDLERS[code])(appId, storeId, data, reply); - } if (!ITypesUtil::Unmarshal(data, appId, storeId)) { ZLOGE("Unmarshal appId:%{public}s storeId:%{public}s", appId.appId.c_str(), storeId.storeId.c_str()); return IPC_STUB_INVALID_DATA_ERR; @@ -225,34 +220,6 @@ int32_t KVDBServiceStub::OnGetSyncParam( return ERR_NONE; } -int32_t KVDBServiceStub::OnGetLocalDevice( - const AppId &appId, const StoreId &storeId, MessageParcel &data, MessageParcel &reply) -{ - (void)appId; - (void)storeId; - int32_t status = SUCCESS; - auto brief = GetLocalDevice(); - if (!ITypesUtil::Marshal(reply, status, brief)) { - ZLOGE("Marshal device brief:{%{public}u, %{public}u}", brief.networkId.empty(), brief.uuid.empty()); - return IPC_STUB_WRITE_PARCEL_ERR; - } - return ERR_NONE; -} - -int32_t KVDBServiceStub::OnGetRemoteDevices( - const AppId &appId, const StoreId &storeId, MessageParcel &data, MessageParcel &reply) -{ - (void)appId; - (void)storeId; - int32_t status = SUCCESS; - auto briefs = GetRemoteDevices(); - if (!ITypesUtil::Marshal(reply, status, briefs)) { - ZLOGE("Marshal device brief:%{public}zu", briefs.size()); - return IPC_STUB_WRITE_PARCEL_ERR; - } - return ERR_NONE; -} - int32_t KVDBServiceStub::OnEnableCap( const AppId &appId, const StoreId &storeId, MessageParcel &data, MessageParcel &reply) { diff --git a/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_service_stub.h b/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_service_stub.h index 8b5f8b90..ab0bacc4 100644 --- a/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_service_stub.h +++ b/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_service_stub.h @@ -43,8 +43,6 @@ private: int32_t OnSubscribe(const AppId &appId, const StoreId &storeId, MessageParcel &data, MessageParcel &reply); int32_t OnUnsubscribe(const AppId &appId, const StoreId &storeId, MessageParcel &data, MessageParcel &reply); int32_t OnGetBackupPassword(const AppId &appId, const StoreId &storeId, MessageParcel &data, MessageParcel &reply); - int32_t OnGetLocalDevice(const AppId &appId, const StoreId &storeId, MessageParcel &data, MessageParcel &reply); - int32_t OnGetRemoteDevices(const AppId &appId, const StoreId &storeId, MessageParcel &data, MessageParcel &reply); static const Handler HANDLERS[TRANS_BUTT]; }; } // namespace OHOS::DistributedKv diff --git a/datamgr_service/services/distributeddataservice/service/kvdb/upgrade.cpp b/datamgr_service/services/distributeddataservice/service/kvdb/upgrade.cpp index 8220ef83..4b662aca 100644 --- a/datamgr_service/services/distributeddataservice/service/kvdb/upgrade.cpp +++ b/datamgr_service/services/distributeddataservice/service/kvdb/upgrade.cpp @@ -20,12 +20,18 @@ #include "crypto_manager.h" #include "metadata/secret_key_meta_data.h" +#include "device_manager_adapter.h" +#include "log_print.h" #include "metadata/meta_data_manager.h" #include "store_cache.h" +#include "accesstoken_kit.h" #include "directory_manager.h" namespace OHOS::DistributedKv { using namespace OHOS::DistributedData; using system_clock = std::chrono::system_clock; +using DMAdapter = DistributedData::DeviceManagerAdapter; +using DBKey = DistributedDB::Key; + Upgrade &Upgrade::GetInstance() { static Upgrade upgrade; @@ -34,6 +40,13 @@ Upgrade &Upgrade::GetInstance() Upgrade::DBStatus Upgrade::UpdateStore(const StoreMeta &old, const StoreMeta &meta, const std::vector &pwd) { + if (old.version < StoreMeta::UUID_CHANGED_TAG && old.storeType == DEVICE_COLLABORATION) { + auto upStatus = Upgrade::GetInstance().UpdateUuid(old, meta, pwd); + if (upStatus != DBStatus::OK) { + return DBStatus::DB_ERROR; + } + } + if (old.dataDir == meta.dataDir) { return DBStatus::OK; } @@ -89,6 +102,28 @@ void Upgrade::UpdatePassword(const StoreMeta &meta, const std::vector & MetaDataManager::GetInstance().SaveMeta(meta.GetSecretKey(), secretKey, true); } +Upgrade::DBStatus Upgrade::UpdateUuid(const StoreMeta &old, const StoreMeta &meta, const std::vector &pwd) +{ + auto kvStore = GetDBStore(meta, pwd); + if (kvStore == nullptr) { + return DBStatus::DB_ERROR; + } + kvStore->RemoveDeviceData(); + auto uuid = GetEncryptedUuidByMeta(meta); + auto dbStatus = kvStore->UpdateKey([uuid](const DBKey &originKey, DBKey &newKey) { + newKey = originKey; + errno_t err = EOK; + err = memcpy_s(newKey.data(), newKey.size(), uuid.data(), uuid.size()); + if (err != EOK) { + ZLOGE("memcpy_s failed, err:%{public}d", err); + } + }); + if (dbStatus != DBStatus::OK) { + ZLOGE("fail to update Uuid, status:%{public}d", dbStatus); + } + return dbStatus; +} + bool Upgrade::RegisterExporter(uint32_t version, Exporter exporter) { (void)version; @@ -117,4 +152,22 @@ Upgrade::AutoStore Upgrade::GetDBStore(const StoreMeta &meta, const std::vector< }); return dbStore; } + +std::string Upgrade::GetEncryptedUuidByMeta(const StoreMeta &meta) +{ + std::string keyUuid = meta.appId + meta.storeId; + if (calcUuid_.Contains(keyUuid)) { + return calcUuid_[keyUuid]; + } + std::string uuid; + if (OHOS::Security::AccessToken::AccessTokenKit::GetTokenTypeFlag(meta.tokenId) == + OHOS::Security::AccessToken::TOKEN_HAP) { + uuid = DMAdapter::GetInstance().CalcClientUuid(meta.appId, meta.deviceId); + calcUuid_.Insert(keyUuid, uuid); + return uuid; + } + uuid = DMAdapter::GetInstance().CalcClientUuid(" ", meta.deviceId); + calcUuid_.Insert(keyUuid, uuid); + return uuid; +} } \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/kvdb/upgrade.h b/datamgr_service/services/distributeddataservice/service/kvdb/upgrade.h index 62644591..b6d83b02 100644 --- a/datamgr_service/services/distributeddataservice/service/kvdb/upgrade.h +++ b/datamgr_service/services/distributeddataservice/service/kvdb/upgrade.h @@ -17,10 +17,13 @@ #define OHOS_DISTRIBUTED_DATA_SERVICE_KVDB_UPGRADE_H #include #include + #include "kv_store_delegate_manager.h" #include "kv_store_nb_delegate.h" #include "metadata/store_meta_data.h" #include "types.h" +#include "concurrent_map.h" + namespace OHOS::DistributedKv { class Upgrade { public: @@ -31,6 +34,7 @@ public: using DBManager = DistributedDB::KvStoreDelegateManager; using Exporter = std::function; using Cleaner = std::function; + API_EXPORT static Upgrade &GetInstance(); API_EXPORT bool RegisterExporter(uint32_t version, Exporter exporter); API_EXPORT bool RegisterCleaner(uint32_t version, Cleaner cleaner); @@ -38,10 +42,14 @@ public: DBStatus UpdateStore(const StoreMeta &old, const StoreMeta &metaData, const std::vector &pwd); DBStatus ExportStore(const StoreMeta &old, const StoreMeta &meta); void UpdatePassword(const StoreMeta &meta, const std::vector &password); + DBStatus UpdateUuid(const StoreMeta &old, const StoreMeta &meta, const std::vector &pwd); + API_EXPORT std::string GetEncryptedUuidByMeta(const StoreMeta &meta); private: using AutoStore = std::unique_ptr>; AutoStore GetDBStore(const StoreMeta &meta, const std::vector &pwd); + ConcurrentMap calcUuid_; + Exporter exporter_; Cleaner cleaner_; }; diff --git a/datamgr_service/services/distributeddataservice/service/kvdb/user_delegate.cpp b/datamgr_service/services/distributeddataservice/service/kvdb/user_delegate.cpp index 5fbd1814..ee66bb38 100644 --- a/datamgr_service/services/distributeddataservice/service/kvdb/user_delegate.cpp +++ b/datamgr_service/services/distributeddataservice/service/kvdb/user_delegate.cpp @@ -53,12 +53,16 @@ std::set UserDelegate::GetLocalUsers() ZLOGE("failed to get local device id"); return {}; } - if (!deviceUserMap_.Contains(deviceId)) { - LoadFromMeta(deviceId); - } std::set users; - deviceUserMap_.ComputeIfPresent(deviceId, [&users](auto&, std::map &value) { - for (auto [user, active] : value) { + deviceUser_.Compute(deviceId, [&users](const auto &key, auto &value) { + if (value.empty()) { + UserMetaData userMetaData; + MetaDataManager::GetInstance().LoadMeta(UserMetaRow::GetKeyFor(key), userMetaData); + for (const auto &user : userMetaData.users) { + value[user.id] = user.isActive; + } + } + for (const auto [user, active] : value) { users.emplace(std::to_string(user)); } return !value.empty(); @@ -78,12 +82,19 @@ std::vector UserDelegate::GetRemoteUserStatus(const std::vector UserDelegate::GetUsers(const std::string &deviceId) { std::vector userStatus; - if (!deviceUserMap_.Contains(deviceId)) { - LoadFromMeta(deviceId); - } - for (const auto &entry : deviceUserMap_[deviceId]) { - userStatus.emplace_back(entry.first, entry.second); - } + deviceUser_.Compute(deviceId, [&userStatus](const auto &key, auto &users) { + if (users.empty()) { + UserMetaData userMetaData; + MetaDataManager::GetInstance().LoadMeta(UserMetaRow::GetKeyFor(key), userMetaData); + for (const auto &user : userMetaData.users) { + users[user.id] = user.isActive; + } + } + for (const auto [key, value] : users) { + userStatus.emplace_back(key, value); + } + return !users.empty(); + }); ZLOGI("device:%{public}s, users:%{public}s", Anonymous::Change(deviceId).c_str(), Serializable::Marshall(userStatus).c_str()); return userStatus; @@ -91,22 +102,20 @@ std::vector UserDelegate::GetUsers(const std::string &deviceId) void UserDelegate::DeleteUsers(const std::string &deviceId) { - deviceUserMap_.Erase(deviceId); + deviceUser_.Erase(deviceId); } void UserDelegate::UpdateUsers(const std::string &deviceId, const std::vector &userStatus) { - ZLOGI("begin, device:%{public}.10s, users:%{public}zu", Anonymous::Change(deviceId).c_str(), userStatus.size()); - deviceUserMap_.Compute(deviceId, [&userStatus](const auto &key, std::map &userMap) { - userMap = {}; - for (auto &user : userStatus) { - userMap[user.id] = user.isActive; + ZLOGI("begin, device:%{public}s, users:%{public}zu", Anonymous::Change(deviceId).c_str(), userStatus.size()); + deviceUser_.Compute(deviceId, [&userStatus](const auto &key, std::map &users) { + users = {}; + for (const auto &user : userStatus) { + users[user.id] = user.isActive; } + ZLOGI("end, device:%{public}s, users:%{public}zu", Anonymous::Change(key).c_str(), users.size()); return true; }); - - ZLOGI("end, device:%{public}s, users:%{public}zu", Anonymous::Change(deviceId).c_str(), - deviceUserMap_[deviceId].size()); } bool UserDelegate::InitLocalUserMeta() @@ -124,25 +133,16 @@ bool UserDelegate::InitLocalUserMeta() UserMetaData userMetaData; userMetaData.deviceId = GetLocalDeviceId(); UpdateUsers(userMetaData.deviceId, userStatus); - for (auto &pair : deviceUserMap_[userMetaData.deviceId]) { - userMetaData.users.emplace_back(pair.first, pair.second); - } - + deviceUser_.ComputeIfPresent(userMetaData.deviceId, [&userMetaData](const auto &, std::map &users) { + for (const auto &[key, value] : users) { + userMetaData.users.emplace_back(key, value); + } + return true; + }); ZLOGI("put user meta data save meta data"); return MetaDataManager::GetInstance().SaveMeta(UserMetaRow::GetKeyFor(userMetaData.deviceId), userMetaData); } -void UserDelegate::LoadFromMeta(const std::string &deviceId) -{ - UserMetaData userMetaData; - MetaDataManager::GetInstance().LoadMeta(UserMetaRow::GetKeyFor(deviceId), userMetaData); - std::map userMap; - for (const auto &user : userMetaData.users) { - userMap[user.id] = user.isActive; - } - deviceUserMap_[deviceId] = userMap; -} - UserDelegate &UserDelegate::GetInstance() { static UserDelegate instance; diff --git a/datamgr_service/services/distributeddataservice/service/kvdb/user_delegate.h b/datamgr_service/services/distributeddataservice/service/kvdb/user_delegate.h index fb3797d6..56dec6c1 100644 --- a/datamgr_service/services/distributeddataservice/service/kvdb/user_delegate.h +++ b/datamgr_service/services/distributeddataservice/service/kvdb/user_delegate.h @@ -56,13 +56,12 @@ private: UserDelegate &userDelegate_; }; std::vector GetUsers(const std::string &deviceId); - void LoadFromMeta(const std::string &deviceId); void UpdateUsers(const std::string &deviceId, const std::vector &userStatus); void DeleteUsers(const std::string &deviceId); bool NotifyUserEvent(const UserEvent &userEvent); // device : { user : isActive } - ConcurrentMap> deviceUserMap_; + ConcurrentMap> deviceUser_; }; } // namespace OHOS::DistributedData diff --git a/datamgr_service/services/distributeddataservice/service/rdb/irdb_result_set.h b/datamgr_service/services/distributeddataservice/service/rdb/irdb_result_set.h index c2e81993..5926784c 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/irdb_result_set.h +++ b/datamgr_service/services/distributeddataservice/service/rdb/irdb_result_set.h @@ -17,10 +17,10 @@ #define DISTRIBUTED_RDB_IRDB_RESULT_SET_H #include "iremote_broker.h" -#include "result_set.h" +#include "remote_result_set.h" namespace OHOS::DistributedRdb { -class IRdbResultSet : public NativeRdb::ResultSet, public IRemoteBroker { +class IRdbResultSet : public NativeRdb::RemoteResultSet, public IRemoteBroker { public: using ColumnType = NativeRdb::ColumnType; virtual ~IRdbResultSet() = default; diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.cpp b/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.cpp index a0a29d01..430d5e30 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.cpp +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.cpp @@ -140,12 +140,16 @@ void RdbServiceImpl::OnClientDied(pid_t pid) bool RdbServiceImpl::CheckAccess(const RdbSyncerParam ¶m) { - auto tokenId = IPCSkeleton::GetCallingTokenID(); - auto instanceId = RdbSyncer::GetInstIndex(tokenId, param.bundleName_); + CheckerManager::StoreInfo storeInfo; + storeInfo.uid = IPCSkeleton::GetCallingUid(); + storeInfo.tokenId = IPCSkeleton::GetCallingTokenID(); + storeInfo.bundleName = param.bundleName_; + storeInfo.storeId = RdbSyncer::RemoveSuffix(param.storeName_); + auto instanceId = RdbSyncer::GetInstIndex(storeInfo.tokenId, storeInfo.bundleName); if (instanceId != 0) { return false; } - return !GetAppId(param.bundleName_).empty(); + return !CheckerManager::GetInstance().GetAppId(storeInfo).empty(); } std::string RdbServiceImpl::ObtainDistributedTableName(const std::string &device, const std::string &table) @@ -349,11 +353,14 @@ std::string RdbServiceImpl::TransferStringToHex(const std::string &origStr) std::string RdbServiceImpl::GenIdentifier(const RdbSyncerParam ¶m) { - auto tokenId = IPCSkeleton::GetCallingTokenID(); - auto user = AccountDelegate::GetInstance()->GetUserByToken(tokenId); - std::string appId = GetAppId(param.bundleName_); + pid_t uid = IPCSkeleton::GetCallingUid(); + uint32_t token = IPCSkeleton::GetCallingTokenID(); + auto storeId = RdbSyncer::RemoveSuffix(param.storeName_); + CheckerManager::StoreInfo storeInfo{ uid, token, param.bundleName_, storeId }; + auto userId = AccountDelegate::GetInstance()->GetUserByToken(token); + std::string appId = CheckerManager::GetInstance().GetAppId(storeInfo); std::string identifier = RelationalStoreManager::GetRelationalStoreIdentifier( - std::to_string(user), appId, RdbSyncer::RemoveSuffix(param.storeName_)); + std::to_string(userId), appId, storeId); return TransferStringToHex(identifier); } @@ -389,15 +396,6 @@ int32_t RdbServiceImpl::RemoteQuery(const RdbSyncerParam& param, const std::stri return syncer->RemoteQuery(device, sql, selectionArgs, resultSet); } -std::string RdbServiceImpl::GetAppId(const std::string &bundleName) -{ - CheckerManager::StoreInfo storeInfo; - storeInfo.uid = IPCSkeleton::GetCallingUid(); - storeInfo.tokenId = IPCSkeleton::GetCallingTokenID(); - storeInfo.bundleName = bundleName; - return CheckerManager::GetInstance().GetAppId(storeInfo); -} - int32_t RdbServiceImpl::CreateRDBTable( const RdbSyncerParam ¶m, const std::string &writePermission, const std::string &readPermission) { diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.h b/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.h index 0961337a..3d2324bd 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.h +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.h @@ -80,8 +80,6 @@ private: void OnAsyncComplete(pid_t pid, uint32_t seqNum, const SyncResult& result); - std::string GetAppId(const std::string &bundleName); - class DeathRecipientImpl : public IRemoteObject::DeathRecipient { public: using DeathCallback = std::function; diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_syncer.cpp b/datamgr_service/services/distributeddataservice/service/rdb/rdb_syncer.cpp index 0e6fc39c..3d47af3e 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_syncer.cpp +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_syncer.cpp @@ -109,9 +109,10 @@ int32_t RdbSyncer::Init( pid_ = pid; uid_ = uid; token_ = token; + StoreMetaData oldMeta; StoreMetaData meta; - if (CreateMetaData(meta) != RDB_OK) { + if (CreateMetaData(meta, oldMeta) != RDB_OK) { ZLOGE("create meta data failed"); return RDB_ERROR; } @@ -119,6 +120,11 @@ int32_t RdbSyncer::Init( ZLOGE("delegate is nullptr"); return RDB_ERROR; } + + if (oldMeta.storeType == RDB_DEVICE_COLLABORATION && oldMeta.version < StoreMetaData::UUID_CHANGED_TAG) { + delegate_->RemoveDeviceData(); + } + ZLOGI("success"); return RDB_OK; } @@ -150,10 +156,9 @@ void RdbSyncer::FillMetaData(StoreMetaData &meta) meta.isEncrypt = param_.isEncrypt_; } -int32_t RdbSyncer::CreateMetaData(StoreMetaData &meta) +int32_t RdbSyncer::CreateMetaData(StoreMetaData &meta, StoreMetaData &old) { FillMetaData(meta); - StoreMetaData old; bool isCreated = MetaDataManager::GetInstance().LoadMeta(meta.GetKey(), old); if (isCreated && (old.storeType != meta.storeType || Constant::NotEqual(old.isEncrypt, meta.isEncrypt) || old.area != meta.area)) { @@ -428,11 +433,10 @@ int32_t RdbSyncer::DoSync(const SyncOption &option, const RdbPredicates &predica } ZLOGI("delegate sync"); - auto status = delegate->Sync(devices, static_cast(option.mode), - MakeQuery(predicates), [&result] (const auto& syncStatus) { - HandleSyncStatus(syncStatus, result); - }, true); - return status == DistributedDB::DBStatus::OK ? RDB_OK : RDB_ERROR; + return delegate->Sync(devices, static_cast(option.mode), + MakeQuery(predicates), [&result] (const auto& syncStatus) { + HandleSyncStatus(syncStatus, result); + }, true); } int32_t RdbSyncer::DoAsync(const SyncOption &option, const RdbPredicates &predicates, const SyncCallback& callback) @@ -451,13 +455,12 @@ int32_t RdbSyncer::DoAsync(const SyncOption &option, const RdbPredicates &predic } ZLOGI("delegate sync"); - auto status = delegate->Sync(devices, static_cast(option.mode), - MakeQuery(predicates), [callback] (const auto& syncStatus) { - SyncResult result; - HandleSyncStatus(syncStatus, result); - callback(result); - }, false); - return status == DistributedDB::DBStatus::OK ? RDB_OK : RDB_ERROR; + return delegate->Sync(devices, static_cast(option.mode), + MakeQuery(predicates), [callback] (const auto& syncStatus) { + SyncResult result; + HandleSyncStatus(syncStatus, result); + callback(result); + }, false); } int32_t RdbSyncer::RemoteQuery(const std::string& device, const std::string& sql, diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_syncer.h b/datamgr_service/services/distributeddataservice/service/rdb/rdb_syncer.h index e049a864..9b5f90b4 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_syncer.h +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_syncer.h @@ -70,7 +70,7 @@ private: std::string GetAppId() const; - int32_t CreateMetaData(StoreMetaData &meta); + int32_t CreateMetaData(StoreMetaData &meta, StoreMetaData &old); void FillMetaData(StoreMetaData &meta); int32_t InitDBDelegate(const StoreMetaData &meta); bool SetSecretKey(const StoreMetaData &meta); diff --git a/datamgr_service/services/distributeddataservice/service/test/BUILD.gn b/datamgr_service/services/distributeddataservice/service/test/BUILD.gn index f334bc90..70ad6fdd 100644 --- a/datamgr_service/services/distributeddataservice/service/test/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/service/test/BUILD.gn @@ -29,7 +29,10 @@ config("module_private_config") { "../../framework/include/", ] - defines = [ "TEST_ON_DEVICE" ] + defines = [ + "TEST_ON_DEVICE", + "OPENSSL_SUPPRESS_DEPRECATED", + ] } ohos_unittest("ConfigFactoryTest") { diff --git a/datamgr_service/services/distributeddataservice/service/test/config_factory_test.cpp b/datamgr_service/services/distributeddataservice/service/test/config_factory_test.cpp index 6430fac4..b1ee7541 100644 --- a/datamgr_service/services/distributeddataservice/service/test/config_factory_test.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/config_factory_test.cpp @@ -61,7 +61,7 @@ HWTEST_F(ConfigFactoryTest, ComponentConfig, TestSize.Level0) { auto *components = ConfigFactory::GetInstance().GetComponentConfig(); ASSERT_NE(components, nullptr); - ASSERT_EQ(components->size(), 2); + ASSERT_EQ(components->size(), 3); const ComponentConfig &config = (*components)[0]; ASSERT_EQ(config.description, "3rd party adapter"); ASSERT_EQ(config.lib, "libconfigdemo.z.so"); diff --git a/datamgr_service/services/distributeddataservice/service/test/mock/db_store_mock.cpp b/datamgr_service/services/distributeddataservice/service/test/mock/db_store_mock.cpp index 9f7e3647..87639965 100644 --- a/datamgr_service/services/distributeddataservice/service/test/mock/db_store_mock.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/mock/db_store_mock.cpp @@ -305,5 +305,10 @@ DBStatus DBStoreMock::DeleteBatch(ConcurrentMap &store, const std::v }); return OK; } + +DBStatus DBStoreMock::UpdateKey(const UpdateKeyCallback &callback) +{ + return NOT_SUPPORT; +} } // namespace DistributedData } // namespace OHOS \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/mock/db_store_mock.h b/datamgr_service/services/distributeddataservice/service/test/mock/db_store_mock.h index eedd339a..e50def98 100644 --- a/datamgr_service/services/distributeddataservice/service/test/mock/db_store_mock.h +++ b/datamgr_service/services/distributeddataservice/service/test/mock/db_store_mock.h @@ -36,6 +36,7 @@ public: using SecurityOption = DistributedDB::SecurityOption; using RemotePushFinishedNotifier = DistributedDB::RemotePushFinishedNotifier; using PushDataInterceptor = DistributedDB::PushDataInterceptor; + using UpdateKeyCallback = DistributedDB::UpdateKeyCallback; DBStatus Get(const Key &key, Value &value) const override; DBStatus GetEntries(const Key &keyPrefix, std::vector &entries) const override; DBStatus GetEntries(const Key &keyPrefix, KvStoreResultSet *&resultSet) const override; @@ -87,6 +88,7 @@ public: DBStatus RemoveDeviceData() override; DBStatus GetKeys(const Key &keyPrefix, std::vector &keys) const override; size_t GetSyncDataSize(const std::string &device) const override; + DBStatus UpdateKey(const UpdateKeyCallback &callback) override; private: static const uint32_t DEFAULT_SIZE = 0; diff --git a/datamgr_service/services/distributeddataservice/test/fuzztest/schemaquery_fuzzer/BUILD.gn b/datamgr_service/services/distributeddataservice/test/fuzztest/schemaquery_fuzzer/BUILD.gn index 57cdc683..d2236940 100644 --- a/datamgr_service/services/distributeddataservice/test/fuzztest/schemaquery_fuzzer/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/test/fuzztest/schemaquery_fuzzer/BUILD.gn @@ -64,6 +64,7 @@ ohos_fuzztest("SchemaQueryFuzzTest") { "OMIT_FLATBUFFER", "RELATIONAL_STORE", "SQLITE_DISTRIBUTE_RELATIONAL", + "OPENSSL_SUPPRESS_DEPRECATED", ] external_deps = [ diff --git a/datamgr_service/test/fuzztest/autolaunch_fuzzer/BUILD.gn b/datamgr_service/test/fuzztest/autolaunch_fuzzer/BUILD.gn index 70d15988..fb3e4402 100644 --- a/datamgr_service/test/fuzztest/autolaunch_fuzzer/BUILD.gn +++ b/datamgr_service/test/fuzztest/autolaunch_fuzzer/BUILD.gn @@ -78,6 +78,7 @@ ohos_fuzztest("AutoLaunchFuzzTest") { "OMIT_FLATBUFFER", "RELATIONAL_STORE", "SQLITE_DISTRIBUTE_RELATIONAL", + "OPENSSL_SUPPRESS_DEPRECATED", ] deps = [ diff --git a/datamgr_service/test/fuzztest/kvstoredisksize_fuzzer/BUILD.gn b/datamgr_service/test/fuzztest/kvstoredisksize_fuzzer/BUILD.gn index fd7b73ab..9ee8840f 100644 --- a/datamgr_service/test/fuzztest/kvstoredisksize_fuzzer/BUILD.gn +++ b/datamgr_service/test/fuzztest/kvstoredisksize_fuzzer/BUILD.gn @@ -79,6 +79,7 @@ ohos_fuzztest("KvStoreDiskSizeFuzzTest") { "OMIT_FLATBUFFER", "RELATIONAL_STORE", "SQLITE_DISTRIBUTE_RELATIONAL", + "OPENSSL_SUPPRESS_DEPRECATED", ] deps = [ diff --git a/kv_store/frameworks/common/executor.h b/kv_store/frameworks/common/executor.h new file mode 100644 index 00000000..a9f7be80 --- /dev/null +++ b/kv_store/frameworks/common/executor.h @@ -0,0 +1,131 @@ +/* + * 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_DISTRIBUTED_DATA_KV_STORE_FRAMEWORKS_COMMON_EXECUTOR_H +#define OHOS_DISTRIBUTED_DATA_KV_STORE_FRAMEWORKS_COMMON_EXECUTOR_H +#include +#include +#include +#include + +#include "priority_queue.h" +namespace OHOS { + +class Executor : public std::enable_shared_from_this { +public: + using TaskId = uint64_t; + using Task = std::function; + using Duration = std::chrono::steady_clock::duration; + using Time = std::chrono::steady_clock::time_point; + static constexpr Time INVALID_TIME = std::chrono::time_point(); + static constexpr Duration INVALID_INTERVAL = std::chrono::milliseconds(0); + static constexpr uint64_t UNLIMITED_TIMES = std::numeric_limits::max(); + static constexpr Duration INVALID_DELAY = std::chrono::seconds(0); + static constexpr TaskId INVALID_TASK_ID = static_cast(0l); + + enum Status { + RUNNING, + IS_STOPPING, + STOPPED + }; + struct InnerTask { + std::function exec; + Duration interval = INVALID_INTERVAL; + uint64_t times = UNLIMITED_TIMES; + TaskId taskId = INVALID_TASK_ID; + Time startTime = INVALID_TIME; + InnerTask() = default; + + bool Valid() const + { + return taskId != INVALID_TASK_ID; + } + }; + + Executor() + : thread_([this] { + Run(); + thread_.detach(); + self_ = nullptr; + }) + { + } + + void Bind(PriorityQueue *queue, std::function)> idle, + std::function, bool)> release) + { + std::unique_lock lock(mutex_); + self_ = shared_from_this(); + waits_ = queue; + idle_ = std::move(idle); + release_ = std::move(release); + condition_.notify_one(); + } + + void Stop(bool wait = false) + { + { + std::unique_lock lock(mutex_); + running_ = IS_STOPPING; + condition_.notify_one(); + } + if (wait) { + thread_.join(); + } + } + +private: + static constexpr Duration TIME_OUT = std::chrono::seconds(2); + void Run() + { + std::unique_lock lock(mutex_); + do { + do { + condition_.wait(lock, [this] { + return running_ == IS_STOPPING || waits_ != nullptr; + }); + while (running_ == RUNNING && waits_ != nullptr && waits_->Size() > 0) { + auto currentTask = waits_->Pop(); + if (!currentTask.Valid()) { + break; + } + lock.unlock(); + currentTask.exec(currentTask); + lock.lock(); + waits_->Finish(currentTask.taskId); + } + if (!idle_(self_) && running_ == RUNNING) { + continue; + } + waits_ = nullptr; + } while (running_ == RUNNING && + condition_.wait_until(lock, std::chrono::steady_clock::now() + TIME_OUT, [this]() { + return waits_ != nullptr; + })); + } while (!release_(self_, running_ == IS_STOPPING)); + running_ = STOPPED; + } + + Status running_ = RUNNING; + std::mutex mutex_; + std::condition_variable condition_; + std::shared_ptr self_; + PriorityQueue *waits_ = nullptr; + std::function)> idle_; + std::function, bool)> release_; + std::thread thread_; +}; +} // namespace OHOS +#endif // OHOS_DISTRIBUTED_DATA_KV_STORE_FRAMEWORKS_COMMON_EXECUTOR_H diff --git a/kv_store/frameworks/common/executor_pool.h b/kv_store/frameworks/common/executor_pool.h index 28fbc95c..776f893f 100644 --- a/kv_store/frameworks/common/executor_pool.h +++ b/kv_store/frameworks/common/executor_pool.h @@ -15,98 +15,204 @@ #ifndef OHOS_DISTRIBUTED_DATA_KV_STORE_FRAMEWORKS_COMMON_EXECUTOR_POOL_H #define OHOS_DISTRIBUTED_DATA_KV_STORE_FRAMEWORKS_COMMON_EXECUTOR_POOL_H +#include +#include +#include +#include +#include + +#include "executor.h" #include "pool.h" +#include "priority_queue.h" namespace OHOS { class ExecutorPool { public: - ~ExecutorPool() { - pool_.Clean([](Executor *executor) { - executor->Stop(true); - }) + using TaskId = Executor::TaskId; + using Task = Executor::Task; + using Duration = Executor::Duration; + using Time = Executor::Time; + using InnerTask = Executor::InnerTask; + using Status = Executor::Status; + static constexpr Time INVALID_TIME = std::chrono::time_point(); + static constexpr Duration INVALID_INTERVAL = std::chrono::milliseconds(0); + static constexpr uint64_t UNLIMITED_TIMES = std::numeric_limits::max(); + static constexpr Duration INVALID_DELAY = std::chrono::seconds(0); + static constexpr TaskId INVALID_TASK_ID = static_cast(0l); + + ExecutorPool(size_t max, size_t min) + { + pool_ = new (std::nothrow) Pool(max, min); + execs_ = new PriorityQueue(InnerTask()); + delayTasks_ = new PriorityQueue(InnerTask()); + taskId_ = INVALID_TASK_ID; } - void Execute() { - InnerTask innerTask; - auto executor = pool_.Get(); - if (executor == nullptr) { - execs_.push_back(innerTask); - return taskId; + ~ExecutorPool() + { + poolStatus = Status::IS_STOPPING; + execs_->Clean(); + delayTasks_->Clean(); + std::shared_ptr scheduler; + { + std::lock_guard scheduleLock(mtx_); + scheduler = std::move(scheduler_); + } + if (scheduler != nullptr) { + scheduler->Stop(true); } - executor.Bind(&execs_, [this](Executor *exe)->bool { - return pool_.Release(exe); + pool_->Clean([](std::shared_ptr executor) { + executor->Stop(true); }); - executor.SetTask(innerTask); + delete execs_; + delete delayTasks_; + delete pool_; + poolStatus = Status::STOPPED; } - void Schedule(Task task) + + TaskId Execute(Task task) { - InnerTask innerTask; - if (scheduler_ == nullptr) { - scheduler_ = pool_.Get(true); - scheduler_.Bind(&delayTask_); - scheduler_.SetTask(startTask); + if (poolStatus != Status::RUNNING) { + return INVALID_TASK_ID; } - auto run = [&innerTask, task, this] { - ExecuteInner(task, innerTask.taskId); - if (innerTask.interval != 0) { - innerTask.time = std::chrono::steady_clock::now() + std::second(innerTask.interval); - delayTask_.push(innerTask); - } - }; + auto run = [task](InnerTask innerTask) { + task(); + }; + return Execute(std::move(run), GenTaskId()); + } + + TaskId Execute(Task task, Duration delay) + { + return Schedule(std::move(task), delay, INVALID_INTERVAL, 1); + } + + TaskId Schedule(Task task, Duration interval) + { + return Schedule(std::move(task), INVALID_DELAY, interval, UNLIMITED_TIMES); + } + + TaskId Schedule(Task task, Duration delay, Duration interval) + { + return Schedule(std::move(task), delay, interval, UNLIMITED_TIMES); + } + + TaskId Schedule(Task task, Duration delay, Duration interval, uint64_t times) + { + InnerTask innerTask; + auto run = [task](InnerTask innerTask) { + task(); + }; innerTask.exec = std::move(run); - delayTask_.push(innerTask); - scheduler_.SetTask(startTask); + innerTask.startTime = std::chrono::steady_clock::now() + delay; + innerTask.interval = interval; + innerTask.times = times; + innerTask.taskId = GenTaskId(); + return Schedule(std::move(innerTask)); } -private: - struct InnerTask { - std::function exec; - }; - class Executor { - public: - void SetTask(InnerTask &innerTask) - { - std::gaud_lock lock; - currentTask_ = innerTask; - notify; + bool Remove(TaskId taskId, bool wait = false) + { + bool res = true; + auto delay = delayTasks_->Find(taskId); + if (!delay.Valid()) { + res = false; } - void Bind(std::queue *queue, std::function idle, std::function release); - { - queue_ = queue; - idle_ = idle; - release_ = relase; - }; - void Stop(bool wait = false) { - running_ = false; - notify; - stop_wait(); + delayTasks_->Remove(taskId, wait); + execs_->Remove(taskId, wait); + return res; + } + + TaskId Reset(TaskId taskId, Duration interval) + { + return Reset(taskId, INVALID_DELAY, interval); + } + + TaskId Reset(TaskId taskId, Duration delay, Duration interval) + { + auto innerTask = delayTasks_->Find(taskId); + if (!innerTask.Valid()) { + return INVALID_TASK_ID; + } + delayTasks_->Remove(taskId, false); + auto startTime = std::chrono::steady_clock::now() + delay; + innerTask.startTime = startTime; + innerTask.interval = interval; + delayTasks_->Push(std::move(innerTask), taskId, startTime); + return taskId; + } + +private: + TaskId Execute(std::function task, TaskId taskId) + { + InnerTask innerTask; + innerTask.exec = task; + innerTask.taskId = taskId; + execs_->Push(std::move(innerTask), taskId, INVALID_TIME); + auto executor = pool_->Get(); + if (executor == nullptr) { + return taskId; + } + executor->Bind( + execs_, + [this](std::shared_ptr exe) { + pool_->Idle(exe); + return true; + }, + [this](std::shared_ptr exe, bool force) -> bool { + return pool_->Release(exe, force); + }); + return taskId; + } + + TaskId Schedule(InnerTask innerTask) + { + auto func = innerTask.exec; + auto id = innerTask.taskId; + auto run = [this, func, id](InnerTask task) { + if (task.interval != INVALID_INTERVAL && --task.times > 0) { + task.startTime = std::chrono::steady_clock::now() + task.interval; + delayTasks_->Push(task, task.taskId, task.startTime); + } + Execute(func, id); }; - private: - void Run() - { - do { - do { - InnerTask task = currentTask_; - while (running_ && task.Valid()) { - task(); - task = waits_.Pop(); + innerTask.exec = run; + delayTasks_->Push(innerTask, innerTask.taskId, innerTask.startTime); + std::lock_guard scheduleLock(mtx_); + if (scheduler_ == nullptr) { + scheduler_ = pool_->Get(true); + scheduler_->Bind( + delayTasks_, + [this](std::shared_ptr exe) { + std::unique_lock lock(mtx_); + if (delayTasks_->Size() != 0) { + return false; } - waits_ = nullptr; - std::gaud_lock lock; - idle_(this); - } while (running_ && wait_time(lock)); - } while (release_(this)); - stop_notify(); + scheduler_ = nullptr; + pool_->Idle(exe); + return true; + }, + [this](std::shared_ptr exe, bool force) -> bool { + return pool_->Release(exe, force); + }); } - bool running_ = true; - std::queue *waits_; - InnerTask currentTask_; - std::thread thread_; - std::function release_; - }; - Pool pool_; - std::shared_ptr scheduler_; - std::queue execs_; - std::queue delayTask_; + return innerTask.taskId; + } + + TaskId GenTaskId() + { + auto taskId = ++taskId_; + if (taskId == INVALID_TASK_ID) { + taskId = ++taskId_; + } + return taskId; + } + + Status poolStatus = Status::RUNNING; + std::mutex mtx_; + Pool *pool_; + std::shared_ptr scheduler_ = nullptr; + PriorityQueue *execs_; + PriorityQueue *delayTasks_; + std::atomic taskId_; }; -} +} // namespace OHOS #endif // OHOS_DISTRIBUTED_DATA_KV_STORE_FRAMEWORKS_COMMON_EXECUTOR_POOL_H diff --git a/kv_store/frameworks/common/pool.h b/kv_store/frameworks/common/pool.h index 0c5e6676..3f761927 100644 --- a/kv_store/frameworks/common/pool.h +++ b/kv_store/frameworks/common/pool.h @@ -15,30 +15,32 @@ #ifndef OHOS_DISTRIBUTED_DATA_KV_STORE_FRAMEWORKS_COMMON_POOL_H #define OHOS_DISTRIBUTED_DATA_KV_STORE_FRAMEWORKS_COMMON_POOL_H +#include +#include namespace OHOS { template class Pool { public: - Pool(uint32_t capability) : capability_(capability) {} - T *Get(bool isForce = false) + Pool(uint32_t capability, uint32_t min) : capability_(capability), min_(min) {} + + std::shared_ptr Get(bool isForce = false) { - std::lock_gurd<> + std::unique_lock lock(mutex_); if (idle_ == nullptr) { if (!isForce && current_ >= capability_) { return nullptr; } auto cur = new Node(); - cur->next = nullptr; - cur->prev = nullptr; idle_ = cur; current_++; } Node *cur = idle_; idle_ = idle_->next; + if (idle_ == nullptr) { + } if (idle_ != nullptr) { idle_->prev = nullptr; } - cur->next = busy_; if (busy_ != nullptr) { cur->prev = busy_->prev; @@ -48,62 +50,85 @@ public: return cur->data; }; - int32_t Release(T *data) + int32_t Release(std::shared_ptr data, bool force = false) { - std::lock_gurd<> - Node *cur = idle_ + std::unique_lock lock(mutex_); + Node *cur = idle_; + if (!force && current_ <= min_) { + return false; + } while (cur != nullptr) { if (cur->data == data) { - cur->next->prev = cur->prev; - cur->prev->next = cur->next; + if (cur->next != nullptr) { + cur->next->prev = cur->prev; + } + if (cur->prev != nullptr) { + cur->prev->next = cur->next; + } if (idle_ == cur) { idle_ = cur->next; } + current_--; delete cur; return true; + } else { + cur = cur->next; + continue; } } return false; } - int32_t Idle(T *data) + void Idle(std::shared_ptr data) { - std::lock_gurd<> - Node *cur = static_cast(data); - cur->next->prev = cur->prev; - cur->prev->next = cur->next; + std::unique_lock lock(mutex_); + Node *cur = busy_; + while (cur != nullptr && cur->data != data) { + cur = cur->next; + } + if (cur == nullptr) { + return; + } + if (cur == busy_) { + busy_ = busy_->next; + } + if (cur->next != nullptr) { + cur->next->prev = cur->prev; + } + if (cur->prev != nullptr) { + cur->prev->next = cur->next; + } cur->prev = nullptr; cur->next = idle_; - idle_->prev = cur; + if (idle_ != nullptr) { + idle_->prev = cur; + } idle_ = cur; } - int32_t Clean(std::function<> close) + int32_t Clean(std::function)> close) { - while(busy_ != nullptr) { - // unlock - close(busy_); - // luck + auto temp = min_; + min_ = 0; + while (busy_ != nullptr) { + close(busy_->data); } - while(idle_ != nullptr) { - // unlock - close(busy_); - // luck + while (idle_ != nullptr) { + close(idle_->data); } + min_ = temp; + return true; } - private: struct Node { Node *prev = nullptr; Node *next = nullptr; - T *data = new T(); - ~Node() { - delete data; - } + std::shared_ptr data = std::make_shared(); }; uint32_t capability_; + uint32_t min_; uint32_t current_ = 0; Node *idle_ = nullptr; Node *busy_ = nullptr; diff --git a/kv_store/frameworks/common/priority_queue.h b/kv_store/frameworks/common/priority_queue.h new file mode 100644 index 00000000..e1afc5f7 --- /dev/null +++ b/kv_store/frameworks/common/priority_queue.h @@ -0,0 +1,122 @@ +/* + * 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_DISTRIBUTED_DATA_FRAMEWORKS_COMMON_PRIORITY_QUEUE_H +#define OHOS_DISTRIBUTED_DATA_FRAMEWORKS_COMMON_PRIORITY_QUEUE_H +#include +#include +#include +#include +#include +#include +namespace OHOS { +template +class PriorityQueue { +public: + struct PQMatrix { + _Tsk task_; + _Tid id_; + PQMatrix(_Tsk task, _Tid id) : task_(task), id_(id) {} + }; + using TskIndex = typename std::map<_Tme, PQMatrix>::iterator; + + PriorityQueue(const _Tsk &task) : INVALID_TSK(std::move(task)) {} + _Tsk Pop() + { + std::unique_lock lock(pqMtx_); + while (!tasks_.empty()) { + if (tasks_.begin()->first > std::chrono::steady_clock::now()) { + popCv_.wait_until(lock, tasks_.begin()->first); + continue; + } + auto temp = tasks_.begin(); + auto id = temp->second.id_; + running.emplace(id); + auto res = std::move(temp->second.task_); + tasks_.erase(temp); + indexes_.erase(id); + return res; + } + return INVALID_TSK; + } + + bool Push(_Tsk tsk, _Tid id, _Tme tme) + { + std::unique_lock lock(pqMtx_); + if (!tsk.Valid()) { + return false; + } + auto temp = tasks_.emplace(tme, PQMatrix(std::move(tsk), id)); + indexes_.emplace(id, temp); + popCv_.notify_all(); + return true; + } + + size_t Size() + { + std::lock_guard lock(pqMtx_); + return tasks_.size(); + } + + _Tsk Find(_Tid id) + { + std::unique_lock lock(pqMtx_); + if (indexes_.find(id) != indexes_.end()) { + return indexes_[id]->second.task_; + } + return INVALID_TSK; + } + + bool Remove(_Tid id, bool wait) + { + std::unique_lock lock(pqMtx_); + removeCv_.wait(lock, [this, id, wait] { + return !wait || running.find(id) == running.end(); + }); + auto index = indexes_.find(id); + if (index == indexes_.end()) { + return false; + } + tasks_.erase(index->second); + indexes_.erase(index); + popCv_.notify_all(); + return true; + } + + void Clean() + { + std::unique_lock lock(pqMtx_); + indexes_.clear(); + tasks_.clear(); + } + + void Finish(_Tid id) + { + std::unique_lock lock(pqMtx_); + running.erase(id); + removeCv_.notify_all(); + } + +private: + const _Tsk INVALID_TSK; + std::mutex pqMtx_; + std::condition_variable popCv_; + std::condition_variable removeCv_; + std::multimap<_Tme, PQMatrix> tasks_; + std::set<_Tid> running; + std::map<_Tid, TskIndex> indexes_; +}; +} // namespace OHOS +#endif //OHOS_DISTRIBUTED_DATA_FRAMEWORKS_COMMON_PRIORITY_QUEUE_H diff --git a/kv_store/frameworks/common/task_scheduler.h b/kv_store/frameworks/common/task_scheduler.h index a8144e92..dd99e323 100644 --- a/kv_store/frameworks/common/task_scheduler.h +++ b/kv_store/frameworks/common/task_scheduler.h @@ -52,7 +52,6 @@ public: } TaskScheduler(const std::string &name) : TaskScheduler(std::numeric_limits::max(), name) {} TaskScheduler(size_t capacity = std::numeric_limits::max()) : TaskScheduler(capacity, "") {} - ~TaskScheduler() { isRunning_ = false; @@ -60,12 +59,6 @@ public: Execute([]() {}); thread_->join(); } - - TaskId Scheduler(const Time &begin, Task task, Duration interval = INVALID_INTERVAL, - uint64_t times = UNLIMITED_TIMES) - { - return At(begin, task, interval, times); - } // execute task at specific time TaskId At(const Time &begin, Task task, Duration interval = INVALID_INTERVAL, uint64_t times = UNLIMITED_TIMES) { @@ -85,7 +78,6 @@ public: indexes_[innerTask.taskId] = it; return innerTask.taskId; } - TaskId Reset(TaskId taskId, const Duration &interval) { std::unique_lock lock(mutex_); @@ -93,17 +85,14 @@ public: running_.interval = interval; return running_.taskId; } - auto index = indexes_.find(taskId); if (index == indexes_.end()) { return INVALID_TASK_ID; } - auto &innerTask = index->second->second; if (innerTask.interval != INVALID_INTERVAL) { innerTask.interval = interval; } - auto it = tasks_.insert({ std::chrono::steady_clock::now() + interval, std::move(innerTask) }); if (it == tasks_.begin() || index->second == tasks_.begin()) { condition_.notify_one(); @@ -112,20 +101,17 @@ public: indexes_[taskId] = it; return taskId; } - void Clean() { std::unique_lock lock(mutex_); indexes_.clear(); tasks_.clear(); } - // execute task periodically with duration TaskId Every(Duration interval, Task task) { return At(std::chrono::steady_clock::now() + interval, task, interval); } - // remove task in SchedulerTask void Remove(TaskId taskId, bool wait = false) { @@ -134,31 +120,27 @@ public: return (!wait || running_.taskId != taskId); }); auto index = indexes_.find(taskId); - if (index != indexes_.end()) { + if (index == indexes_.end()) { return; } tasks_.erase(index->second); indexes_.erase(index); condition_.notify_one(); } - // execute task periodically with duration after delay TaskId Every(Duration delay, Duration interval, Task task) { return At(std::chrono::steady_clock::now() + delay, task, interval); } - // execute task for some times periodically with duration after delay TaskId Every(int32_t times, Duration delay, Duration interval, Task task) { return At(std::chrono::steady_clock::now() + delay, task, interval, times); } - TaskId Execute(Task task) { return At(std::chrono::steady_clock::now(), std::move(task)); } - private: struct InnerTask { TaskId taskId = INVALID_TASK_ID; @@ -187,11 +169,9 @@ private: tasks_.erase(it); running_.times--; } - if (exec) { exec(); } - { std::unique_lock lock(mutex_); if (running_.interval != INVALID_INTERVAL && running_.times > 0) { diff --git a/kv_store/frameworks/common/test/concurrent_map_test.cpp b/kv_store/frameworks/common/test/concurrent_map_test.cpp index 0136a8d5..0ef31a68 100644 --- a/kv_store/frameworks/common/test/concurrent_map_test.cpp +++ b/kv_store/frameworks/common/test/concurrent_map_test.cpp @@ -125,4 +125,4 @@ HWTEST_F(ConcurrentMapTest, EmplaceWithArgs, TestSize.Level0) ASSERT_EQ(it.second.name, value.name); ASSERT_EQ(it.second.testCase, value.testCase); } -} \ No newline at end of file +} // namespace OHOS::Test \ No newline at end of file diff --git a/kv_store/frameworks/common/test/lru_bucket_test.cpp b/kv_store/frameworks/common/test/lru_bucket_test.cpp index f0965da8..50f7dfbf 100644 --- a/kv_store/frameworks/common/test/lru_bucket_test.cpp +++ b/kv_store/frameworks/common/test/lru_bucket_test.cpp @@ -17,7 +17,7 @@ #include "lru_bucket.h" #include "gtest/gtest.h" - +namespace OHOS::Test { using namespace testing::ext; template using LRUBucket = OHOS::LRUBucket<_Key, _Tp>; @@ -316,4 +316,5 @@ HWTEST_F(LRUBucketTest, update_several, TestSize.Level0) ASSERT_TRUE(bucket_.Get("test_9", value)); ASSERT_TRUE(bucket_.Get("test_8", value)); ASSERT_TRUE(bucket_.Get("test_7", value)); -} \ No newline at end of file +} +} // namespace OHOS::Test \ No newline at end of file diff --git a/kv_store/frameworks/common/test/task_scheduler_test.cpp b/kv_store/frameworks/common/test/task_scheduler_test.cpp index 67e27fc2..e4a1c667 100644 --- a/kv_store/frameworks/common/test/task_scheduler_test.cpp +++ b/kv_store/frameworks/common/test/task_scheduler_test.cpp @@ -18,14 +18,14 @@ #include #include "block_data.h" - +namespace OHOS::Test { using namespace testing::ext; using namespace OHOS; using duration = std::chrono::steady_clock::duration; class TaskSchedulerTest : public testing::Test { public: - static constexpr uint32_t SHORT_INTERVAL = 100; - static constexpr uint32_t LONG_INTERVAL = 300; + static constexpr uint32_t SHORT_INTERVAL = 100; // ms + static constexpr uint32_t LONG_INTERVAL = 1; // s static void SetUpTestCase(void){}; static void TearDownTestCase(void){}; void SetUp(){}; @@ -62,21 +62,23 @@ HWTEST_F(TaskSchedulerTest, At, TestSize.Level0) /** * @tc.name: Every -* @tc.desc: +* @tc.desc:execute task periodically with duration * @tc.type: FUNC * @tc.require: * @tc.author: ht */ -HWTEST_F(TaskSchedulerTest, Every, TestSize.Level0) +HWTEST_F(TaskSchedulerTest, ExecuteDuration, TestSize.Level0) { TaskScheduler taskScheduler("everyTest"); auto blockData = std::make_shared>(LONG_INTERVAL, 0); - taskScheduler.Every(std::chrono::milliseconds(SHORT_INTERVAL), [blockData]() { - int testData = 1; + int testData = 0; + taskScheduler.Every(std::chrono::milliseconds(SHORT_INTERVAL), [blockData, &testData]() { + testData++; blockData->SetValue(testData); }); - for (int i = 1; i < 5; ++i) { - ASSERT_EQ(blockData->GetValue(), 1); + for (int i = 1; i < 10; ++i) { + ASSERT_EQ(blockData->GetValue(), i); + blockData->Clear(0); } } @@ -151,3 +153,109 @@ HWTEST_F(TaskSchedulerTest, Reset3, TestSize.Level0) auto resetTaskId = taskScheduler.Reset(atTaskId, std::chrono::milliseconds(0)); ASSERT_EQ(resetTaskId, TaskScheduler::INVALID_TASK_ID); } + +/** +* @tc.name: Every +* @tc.desc: execute task for some times periodically with duration. +* @tc.type: FUNC +* @tc.require: +* @tc.author: zuojiangjiang +*/ +HWTEST_F(TaskSchedulerTest, EveryExecuteTimes, TestSize.Level0) +{ + TaskScheduler taskScheduler("everyTimes"); + auto blockData = std::make_shared>(LONG_INTERVAL, 0); + int testData = 0; + int times = 5; + auto taskId = taskScheduler.Every(times, std::chrono::milliseconds(0), + std::chrono::milliseconds(SHORT_INTERVAL), [blockData, times, &testData]() { + testData++; + if (testData < times) { + blockData->Clear(testData); + return; + } + blockData->SetValue(testData); + }); + ASSERT_EQ(blockData->GetValue(), times); + auto resetId = taskScheduler.Reset(taskId, std::chrono::milliseconds(SHORT_INTERVAL)); + ASSERT_EQ(resetId, TaskScheduler::INVALID_TASK_ID); + ASSERT_EQ(blockData->GetValue(), times); +} + +/** +* @tc.name: Remove +* @tc.desc: remove task before execute. +* @tc.type: FUNC +* @tc.require: +* @tc.author: zuojiangjiang +*/ +HWTEST_F(TaskSchedulerTest, RemoveBeforeExecute, TestSize.Level0) +{ + TaskScheduler taskScheduler("RemoveBeforeExecute"); + auto expiredTime = std::chrono::steady_clock::now() + std::chrono::milliseconds(SHORT_INTERVAL); + auto blockData = std::make_shared>(LONG_INTERVAL, 0); + int testData = 0; + auto taskId = taskScheduler.At(expiredTime, [blockData, testData]() { + int tmpData = testData + 1; + blockData->SetValue(tmpData); + }, std::chrono::milliseconds(SHORT_INTERVAL)); + taskScheduler.Remove(taskId); + auto resetId = taskScheduler.Reset(taskId, std::chrono::milliseconds(SHORT_INTERVAL)); + ASSERT_EQ(resetId, TaskScheduler::INVALID_TASK_ID); + ASSERT_EQ(blockData->GetValue(), testData); +} + +/** +* @tc.name: Remove +* @tc.desc: remove task during execute, and waiting. +* @tc.type: FUNC +* @tc.require: +* @tc.author: zuojiangjiang +*/ +HWTEST_F(TaskSchedulerTest, RemoveWaitExecute, TestSize.Level0) +{ + TaskScheduler taskScheduler("RemoveWaitExecute"); + auto expiredTime = std::chrono::steady_clock::now() + std::chrono::milliseconds(0); + auto blockDataTest = std::make_shared>(LONG_INTERVAL, 0); + auto blockDataWait = std::make_shared>(LONG_INTERVAL, 0); + int testData = 1; + auto taskId = taskScheduler.At(expiredTime, [blockDataTest, blockDataWait, &testData]() { + blockDataTest->SetValue(testData); + blockDataWait->GetValue(); + int tmpData = testData + 1; + blockDataTest->SetValue(tmpData); + }, std::chrono::milliseconds(SHORT_INTERVAL)); + ASSERT_EQ(blockDataTest->GetValue(), testData); + auto resetId = taskScheduler.Reset(taskId, std::chrono::milliseconds(SHORT_INTERVAL)); + ASSERT_EQ(taskId, resetId); + taskScheduler.Remove(taskId, true); + ASSERT_EQ(blockDataTest->GetValue(), testData + 1); +} + +/** +* @tc.name: Remove +* @tc.desc: remove task during execute, but no wait. +* @tc.type: FUNC +* @tc.require: +* @tc.author: zuojiangjiang +*/ +HWTEST_F(TaskSchedulerTest, RemoveNoWaitExecute, TestSize.Level0) +{ + TaskScheduler taskScheduler("RemoveNoWaitExecute"); + auto expiredTime = std::chrono::steady_clock::now() + std::chrono::milliseconds(0); + auto blockDataTest = std::make_shared>(LONG_INTERVAL, 0); + auto blockDataWait = std::make_shared>(LONG_INTERVAL, 0); + int testData = 1; + auto taskId = taskScheduler.At(expiredTime, [blockDataTest, blockDataWait, &testData]() { + blockDataTest->SetValue(testData); + blockDataWait->GetValue(); + int tmpData = testData + 1; + blockDataTest->SetValue(tmpData); + }); + ASSERT_EQ(blockDataTest->GetValue(), testData); + blockDataTest->Clear(0); + taskScheduler.Remove(taskId); + blockDataWait->SetValue(testData); + ASSERT_EQ(blockDataTest->GetValue(), testData + 1); +} +} // namespace OHOS::Test \ No newline at end of file diff --git a/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/device_kvstore_test.cpp b/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/device_kvstore_test.cpp index 88d7c699..5d7e5e71 100644 --- a/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/device_kvstore_test.cpp +++ b/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/device_kvstore_test.cpp @@ -236,7 +236,7 @@ HWTEST_F(DeviceKvStoreTest, GetDataQueryEntriesAndResultSet, TestSize.Level1) // prepare 10 size_t sum = 10; - int sumGet = 10; + int sumGet = 0; std::string prefix = "prefix_"; for (size_t i = 0; i < sum; i++) { kvStore_->Put({prefix + std::to_string(i)}, {std::to_string(i)}); diff --git a/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/distributed_kv_data_manager_test.cpp b/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/distributed_kv_data_manager_test.cpp index 4821a1bc..e65db8d5 100644 --- a/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/distributed_kv_data_manager_test.cpp +++ b/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/distributed_kv_data_manager_test.cpp @@ -711,18 +711,4 @@ HWTEST_F(DistributedKvDataManagerTest, RegisterKvStoreServiceDeathRecipient001, manager.RegisterKvStoreServiceDeathRecipient(kvStoreDeathRecipient); kvStoreDeathRecipient->OnRemoteDied(); } - -/** -* @tc.name: UnRegisterKvStoreServiceDeathRecipient001 -* @tc.desc: Unregister the callback called when the service dies. -* @tc.type: FUNC -* @tc.require: AR000CQDUS AR000CQDU1 -* @tc.author: liqiao -*/ -HWTEST_F(DistributedKvDataManagerTest, UnRegisterKvStoreServiceDeathRecipient001, TestSize.Level1) -{ - ZLOGI("UnRegisterKvStoreServiceDeathRecipient001 begin."); - std::shared_ptr kvStoreDeathRecipientPtr = std::make_shared(); - manager.UnRegisterKvStoreServiceDeathRecipient(kvStoreDeathRecipientPtr); -} } // namespace OHOS::Test \ No newline at end of file diff --git a/kv_store/frameworks/innerkitsimpl/kvdb/include/dev_manager.h b/kv_store/frameworks/innerkitsimpl/kvdb/include/dev_manager.h index d04cf321..30b18d33 100644 --- a/kv_store/frameworks/innerkitsimpl/kvdb/include/dev_manager.h +++ b/kv_store/frameworks/innerkitsimpl/kvdb/include/dev_manager.h @@ -32,7 +32,7 @@ public: std::string ToUUID(const std::string &networkId); std::string ToNetworkId(const std::string &uuid); const DetailInfo &GetLocalDevice(); - std::vector GetRemoteDevices() const; + std::vector GetRemoteDevices(); class Observer { public: Observer() = default; diff --git a/kv_store/frameworks/innerkitsimpl/kvdb/include/kvdb_service.h b/kv_store/frameworks/innerkitsimpl/kvdb/include/kvdb_service.h index 74af08fb..c343d06a 100644 --- a/kv_store/frameworks/innerkitsimpl/kvdb/include/kvdb_service.h +++ b/kv_store/frameworks/innerkitsimpl/kvdb/include/kvdb_service.h @@ -63,8 +63,6 @@ public: virtual Status Unsubscribe(const AppId &appId, const StoreId &storeId, sptr observer) = 0; virtual Status GetBackupPassword( const AppId &appId, const StoreId &storeId, std::vector &password) = 0; - virtual DevBrief GetLocalDevice() = 0; - virtual std::vector GetRemoteDevices() = 0; protected: enum TransId : int32_t { @@ -86,11 +84,7 @@ protected: TRANS_SUB, TRANS_UNSUB, TRANS_GET_PASSWORD, - TRANS_NO_APPID_BEGIN, - TRANS_GET_LOCAL_DEVICE = TRANS_NO_APPID_BEGIN, - TRANS_GET_REMOTE_DEVICES, - TRANS_NO_APPID_END, - TRANS_BUTT = TRANS_NO_APPID_END, + TRANS_BUTT, }; }; } // namespace OHOS::DistributedKv diff --git a/kv_store/frameworks/innerkitsimpl/kvdb/include/kvdb_service_client.h b/kv_store/frameworks/innerkitsimpl/kvdb/include/kvdb_service_client.h index b38c055a..94adb555 100644 --- a/kv_store/frameworks/innerkitsimpl/kvdb/include/kvdb_service_client.h +++ b/kv_store/frameworks/innerkitsimpl/kvdb/include/kvdb_service_client.h @@ -48,8 +48,6 @@ public: Status Subscribe(const AppId &appId, const StoreId &storeId, sptr observer) override; Status Unsubscribe(const AppId &appId, const StoreId &storeId, sptr observer) override; Status GetBackupPassword(const AppId &appId, const StoreId &storeId, std::vector &password) override; - DevBrief GetLocalDevice() override; - std::vector GetRemoteDevices() override; sptr GetSyncAgent(const AppId &appId); protected: diff --git a/kv_store/frameworks/innerkitsimpl/kvdb/include/observer_bridge.h b/kv_store/frameworks/innerkitsimpl/kvdb/include/observer_bridge.h index 1d53bdc8..85991d85 100644 --- a/kv_store/frameworks/innerkitsimpl/kvdb/include/observer_bridge.h +++ b/kv_store/frameworks/innerkitsimpl/kvdb/include/observer_bridge.h @@ -33,6 +33,7 @@ public: Status RegisterRemoteObserver(); Status UnregisterRemoteObserver(); void OnChange(const DBChangedData &data) override; + void OnServiceDeath(); private: class ObserverClient : public KvStoreObserverClient { diff --git a/kv_store/frameworks/innerkitsimpl/kvdb/include/single_store_impl.h b/kv_store/frameworks/innerkitsimpl/kvdb/include/single_store_impl.h index 00bfeb3a..87f0ab5e 100644 --- a/kv_store/frameworks/innerkitsimpl/kvdb/include/single_store_impl.h +++ b/kv_store/frameworks/innerkitsimpl/kvdb/include/single_store_impl.h @@ -22,12 +22,15 @@ #include "dev_manager.h" #include "kv_store_nb_delegate.h" #include "kvdb_service.h" +#include "kvstore_death_recipient.h" #include "observer_bridge.h" #include "single_kvstore.h" #include "sync_observer.h" namespace OHOS::DistributedKv { -class SingleStoreImpl : public SingleKvStore, public DevManager::Observer { +class SingleStoreImpl : public SingleKvStore, + public DevManager::Observer, + public KvStoreDeathRecipient { public: using Observer = KvStoreObserver; using SyncCallback = KvStoreSyncCallback; @@ -67,6 +70,7 @@ public: std::map &status) override; void Online(const std::string &device) override; void Offline(const std::string &device) override; + void OnRemoteDied() override; // normal function int32_t Close(bool isForce = false); @@ -99,6 +103,7 @@ private: std::function BridgeReleaser(); Status DoSync(const SyncInfo &syncInfo, std::shared_ptr observer); void DoAutoSync(); + void Register(); bool autoSync_ = false; int32_t ref_ = 1; @@ -111,6 +116,8 @@ private: std::shared_ptr dbStore_ = nullptr; std::shared_ptr syncObserver_ = nullptr; ConcurrentMap>> observers_; + static constexpr int32_t INTERVAL = 500; // ms + uint64_t taskId_ = 0; }; } // namespace OHOS::DistributedKv #endif // OHOS_DISTRIBUTED_DATA_FRAMEWORKS_KVDB_SINGLE_STORE_IMPL_H diff --git a/kv_store/frameworks/innerkitsimpl/kvdb/include/task_executor.h b/kv_store/frameworks/innerkitsimpl/kvdb/include/task_executor.h index 4348b561..5a10d5df 100644 --- a/kv_store/frameworks/innerkitsimpl/kvdb/include/task_executor.h +++ b/kv_store/frameworks/innerkitsimpl/kvdb/include/task_executor.h @@ -20,7 +20,8 @@ namespace OHOS::DistributedKv { class TaskExecutor { public: static TaskExecutor &GetInstance(); - bool Execute(TaskScheduler::Task &&task, int32_t interval = 0); + TaskScheduler::TaskId Execute(TaskScheduler::Task &&task, int32_t interval = 0); + void RemoveTask(TaskScheduler::TaskId taskId); private: TaskExecutor(); diff --git a/kv_store/frameworks/innerkitsimpl/kvdb/src/dev_manager.cpp b/kv_store/frameworks/innerkitsimpl/kvdb/src/dev_manager.cpp index 76199f4b..81659945 100644 --- a/kv_store/frameworks/innerkitsimpl/kvdb/src/dev_manager.cpp +++ b/kv_store/frameworks/innerkitsimpl/kvdb/src/dev_manager.cpp @@ -24,6 +24,7 @@ #include "task_executor.h" namespace OHOS::DistributedKv { using namespace OHOS::DistributedHardware; +using DevInfo = OHOS::DistributedHardware::DmDeviceInfo; constexpr int32_t DM_OK = 0; constexpr int32_t DM_ERROR = -1; constexpr size_t DevManager::MAX_ID_LEN; @@ -163,39 +164,45 @@ const DevManager::DetailInfo &DevManager::GetLocalDevice() if (!localInfo_.uuid.empty()) { return localInfo_; } - auto service = KVDBServiceClient::GetInstance(); - if (service == nullptr) { - ZLOGE("service unavailable"); + DevInfo info; + auto ret = DeviceManager::GetInstance().GetLocalDeviceInfo(PKG_NAME, info); + if (ret != DM_OK) { + ZLOGE("get local device info fail"); return invalidDetail_; } - auto device = service->GetLocalDevice(); - if (device.uuid.empty() || device.networkId.empty()) { + auto networkId = std::string(info.networkId); + std::string uuid; + DeviceManager::GetInstance().GetEncryptedUuidByNetworkId(PKG_NAME, networkId, uuid); + if (uuid.empty() || networkId.empty()) { return invalidDetail_; } - localInfo_.networkId = std::move(device.networkId); - localInfo_.uuid = std::move(device.uuid); - ZLOGI("[LocalDevice] uuid:%{public}s, networkId:%{public}s", - StoreUtil::Anonymous(localInfo_.uuid).c_str(), StoreUtil::Anonymous(localInfo_.networkId).c_str()); + localInfo_.networkId = std::move(networkId); + localInfo_.uuid = std::move(uuid); + ZLOGI("[LocalDevice] uuid:%{public}s, networkId:%{public}s", StoreUtil::Anonymous(localInfo_.uuid).c_str(), + StoreUtil::Anonymous(localInfo_.networkId).c_str()); return localInfo_; } -std::vector DevManager::GetRemoteDevices() const +std::vector DevManager::GetRemoteDevices() { - auto service = KVDBServiceClient::GetInstance(); - if (service == nullptr) { - ZLOGE("service unavailable"); + std::vector dmInfos; + auto ret = DeviceManager::GetInstance().GetTrustedDeviceList(PKG_NAME, "", dmInfos); + if (ret != DM_OK) { + ZLOGE("get trusted device:%{public}d", ret); return {}; } - auto devices = service->GetRemoteDevices(); - if (devices.empty()) { + if (dmInfos.empty()) { ZLOGD("no remote device"); return {}; } std::vector dtInfos; - for (auto &device : devices) { + for (auto &device : dmInfos) { DetailInfo dtInfo; + auto networkId = std::string(device.networkId); + std::string uuid; + DeviceManager::GetInstance().GetEncryptedUuidByNetworkId(PKG_NAME, networkId, uuid); dtInfo.networkId = std::move(device.networkId); - dtInfo.uuid = std::move(device.uuid); + dtInfo.uuid = std::move(uuid); dtInfos.push_back(dtInfo); } return dtInfos; diff --git a/kv_store/frameworks/innerkitsimpl/kvdb/src/kvdb_service_client.cpp b/kv_store/frameworks/innerkitsimpl/kvdb/src/kvdb_service_client.cpp index a6279327..3dcfa4e9 100644 --- a/kv_store/frameworks/innerkitsimpl/kvdb/src/kvdb_service_client.cpp +++ b/kv_store/frameworks/innerkitsimpl/kvdb/src/kvdb_service_client.cpp @@ -74,10 +74,15 @@ std::shared_ptr KVDBServiceClient::GetInstance() return nullptr; } - sptr client = iface_cast(service); + sptr client = nullptr; + if (service->IsProxyObject()) { + client = iface_cast(service); + } + if (client == nullptr) { client = new (std::nothrow) KVDBServiceClient(service); } + if (client == nullptr) { return nullptr; } @@ -290,29 +295,6 @@ Status KVDBServiceClient::GetBackupPassword( return static_cast(status); } -KVDBService::DevBrief KVDBServiceClient::GetLocalDevice() -{ - DevBrief brief; - MessageParcel reply; - int32_t status = IPC_SEND(TRANS_GET_LOCAL_DEVICE, reply); - if (status != SUCCESS) { - ZLOGE("status:0x%{public}x", status); - } - ITypesUtil::Unmarshal(reply, brief); - return brief; -} - -std::vector KVDBServiceClient::GetRemoteDevices() -{ - std::vector briefs; - MessageParcel reply; - int32_t status = IPC_SEND(TRANS_GET_REMOTE_DEVICES, reply); - if (status != SUCCESS) { - ZLOGE("status:0x%{public}x", status); - } - ITypesUtil::Unmarshal(reply, briefs); - return briefs; -} sptr KVDBServiceClient::GetSyncAgent(const AppId &appId) { diff --git a/kv_store/frameworks/innerkitsimpl/kvdb/src/observer_bridge.cpp b/kv_store/frameworks/innerkitsimpl/kvdb/src/observer_bridge.cpp index 85019f86..373c8bf5 100644 --- a/kv_store/frameworks/innerkitsimpl/kvdb/src/observer_bridge.cpp +++ b/kv_store/frameworks/innerkitsimpl/kvdb/src/observer_bridge.cpp @@ -106,4 +106,12 @@ std::vector ObserverBridge::ConvertDB(const T &dbEntries, std::string &de } return entries; } + +void ObserverBridge::OnServiceDeath() +{ + if (remote_ == nullptr) { + return; + } + remote_ = nullptr; +} } // namespace OHOS::DistributedKv diff --git a/kv_store/frameworks/innerkitsimpl/kvdb/src/security_manager.cpp b/kv_store/frameworks/innerkitsimpl/kvdb/src/security_manager.cpp index 30825703..ce279b40 100644 --- a/kv_store/frameworks/innerkitsimpl/kvdb/src/security_manager.cpp +++ b/kv_store/frameworks/innerkitsimpl/kvdb/src/security_manager.cpp @@ -70,21 +70,23 @@ SecurityManager::DBPassword SecurityManager::GetDBPassword(const std::string &na { DBPassword dbPassword; auto secKey = LoadKeyFromFile(name, path, dbPassword.isKeyOutdated); + std::vector key{}; + if (secKey.empty() && needCreate) { - secKey = Random(KEY_SIZE); - if (!SaveKeyToFile(name, path, secKey)) { + key = Random(KEY_SIZE); + if (!SaveKeyToFile(name, path, key)) { secKey.assign(secKey.size(), 0); + key.assign(key.size(), 0); return dbPassword; } } - std::vector secretKey{}; - if (Decrypt(secKey, secretKey)) { - dbPassword.SetValue(secKey.data(), secKey.size()); + if ((!secKey.empty() && Decrypt(secKey, key)) || !key.empty()) { + dbPassword.SetValue(key.data(), key.size()); } secKey.assign(secKey.size(), 0); - secretKey.assign(secKey.size(), 0); + key.assign(key.size(), 0); return dbPassword; } diff --git a/kv_store/frameworks/innerkitsimpl/kvdb/src/single_store_impl.cpp b/kv_store/frameworks/innerkitsimpl/kvdb/src/single_store_impl.cpp index e79f8a38..1ec7e803 100644 --- a/kv_store/frameworks/innerkitsimpl/kvdb/src/single_store_impl.cpp +++ b/kv_store/frameworks/innerkitsimpl/kvdb/src/single_store_impl.cpp @@ -23,6 +23,7 @@ #include "log_print.h" #include "store_result_set.h" #include "store_util.h" +#include "task_executor.h" namespace OHOS::DistributedKv { using namespace OHOS::DistributedDataDfx; using namespace std::chrono; @@ -56,6 +57,9 @@ SingleStoreImpl::~SingleStoreImpl() if (interval_ > 0) { DevManager::GetInstance().Unregister(this); } + if (taskId_ > 0) { + TaskExecutor::GetInstance().RemoveTask(taskId_); + } } StoreId SingleStoreImpl::GetStoreId() const @@ -514,7 +518,7 @@ Status SingleStoreImpl::UnRegisterSyncCallback() Status SingleStoreImpl::SetSyncParam(const KvSyncParam &syncParam) { - DdsTrace trace(std::string(LOG_TAG "::") + std::string(__FUNCTION__), true); + DdsTrace trace(std::string(LOG_TAG "::") + std::string(__FUNCTION__), TraceSwitch::BYTRACE_ON); auto service = KVDBServiceClient::GetInstance(); if (service == nullptr) { return SERVER_UNAVAILABLE; @@ -524,7 +528,7 @@ Status SingleStoreImpl::SetSyncParam(const KvSyncParam &syncParam) Status SingleStoreImpl::GetSyncParam(KvSyncParam &syncParam) { - DdsTrace trace(std::string(LOG_TAG "::") + std::string(__FUNCTION__), true); + DdsTrace trace(std::string(LOG_TAG "::") + std::string(__FUNCTION__), TraceSwitch::BYTRACE_ON); auto service = KVDBServiceClient::GetInstance(); if (service == nullptr) { return SERVER_UNAVAILABLE; @@ -534,7 +538,7 @@ Status SingleStoreImpl::GetSyncParam(KvSyncParam &syncParam) Status SingleStoreImpl::SetCapabilityEnabled(bool enabled) const { - DdsTrace trace(std::string(LOG_TAG "::") + std::string(__FUNCTION__), true); + DdsTrace trace(std::string(LOG_TAG "::") + std::string(__FUNCTION__), TraceSwitch::BYTRACE_ON); auto service = KVDBServiceClient::GetInstance(); if (service == nullptr) { return SERVER_UNAVAILABLE; @@ -548,7 +552,7 @@ Status SingleStoreImpl::SetCapabilityEnabled(bool enabled) const Status SingleStoreImpl::SetCapabilityRange(const std::vector &localLabels, const std::vector &remoteLabels) const { - DdsTrace trace(std::string(LOG_TAG "::") + std::string(__FUNCTION__), true); + DdsTrace trace(std::string(LOG_TAG "::") + std::string(__FUNCTION__), TraceSwitch::BYTRACE_ON); auto service = KVDBServiceClient::GetInstance(); if (service == nullptr) { return SERVER_UNAVAILABLE; @@ -558,7 +562,7 @@ Status SingleStoreImpl::SetCapabilityRange(const std::vector &local Status SingleStoreImpl::SubscribeWithQuery(const std::vector &devices, const DataQuery &query) { - DdsTrace trace(std::string(LOG_TAG "::") + std::string(__FUNCTION__), true); + DdsTrace trace(std::string(LOG_TAG "::") + std::string(__FUNCTION__), TraceSwitch::BYTRACE_ON); auto service = KVDBServiceClient::GetInstance(); if (service == nullptr) { return SERVER_UNAVAILABLE; @@ -579,7 +583,7 @@ Status SingleStoreImpl::SubscribeWithQuery(const std::vector &devic Status SingleStoreImpl::UnsubscribeWithQuery(const std::vector &devices, const DataQuery &query) { - DdsTrace trace(std::string(LOG_TAG "::") + std::string(__FUNCTION__), true); + DdsTrace trace(std::string(LOG_TAG "::") + std::string(__FUNCTION__), TraceSwitch::BYTRACE_ON); auto service = KVDBServiceClient::GetInstance(); if (service == nullptr) { return SERVER_UNAVAILABLE; @@ -814,4 +818,43 @@ void SingleStoreImpl::Online(const std::string &device) void SingleStoreImpl::Offline(const std::string &device) { } + +void SingleStoreImpl::OnRemoteDied() +{ + std::shared_lock lock(rwMutex_); + if (taskId_ > 0) { + return; + } + observers_.ForEach([](const auto &, std::pair> &pair) { + if ((pair.first & SUBSCRIBE_TYPE_REMOTE) == SUBSCRIBE_TYPE_REMOTE) { + pair.second->OnServiceDeath(); + } + return false; + }); + taskId_ = TaskExecutor::GetInstance().Execute([this]() { + Register(); + }, INTERVAL); +} + +void SingleStoreImpl::Register() +{ + std::shared_lock lock(rwMutex_); + Status status = SUCCESS; + observers_.ForEach([&status](const auto &, std::pair> &pair) { + if ((pair.first & SUBSCRIBE_TYPE_REMOTE) == SUBSCRIBE_TYPE_REMOTE) { + status = pair.second->RegisterRemoteObserver(); + if (status != SUCCESS) { + return true; + } + } + return false; + }); + if (status != SUCCESS) { + taskId_ = TaskExecutor::GetInstance().Execute([this]() { + Register(); + }, INTERVAL); + } else { + taskId_ = 0; + } +} } // namespace OHOS::DistributedKv \ No newline at end of file diff --git a/kv_store/frameworks/innerkitsimpl/kvdb/src/store_factory.cpp b/kv_store/frameworks/innerkitsimpl/kvdb/src/store_factory.cpp index 2e64222c..2cc33ef6 100644 --- a/kv_store/frameworks/innerkitsimpl/kvdb/src/store_factory.cpp +++ b/kv_store/frameworks/innerkitsimpl/kvdb/src/store_factory.cpp @@ -17,6 +17,7 @@ #include "backup_manager.h" #include "device_convertor.h" +#include "kvstore_service_death_notifier.h" #include "log_print.h" #include "security_manager.h" #include "single_store_impl.h" @@ -105,6 +106,7 @@ std::shared_ptr StoreFactory::GetOrOpenStore(const AppId &appId, } isCreate = true; stores[storeId] = kvStore; + KvStoreServiceDeathNotifier::AddServiceDeathWatcher(kvStore); return !stores.empty(); }); return kvStore; @@ -132,6 +134,7 @@ Status StoreFactory::Close(const AppId &appId, const StoreId &storeId, bool isFo status = SUCCESS; auto ref = it->second->Close(isForce); if (ref <= 0) { + KvStoreServiceDeathNotifier::RemoveServiceDeathWatcher(it->second); it = values.erase(it); } else { ++it; diff --git a/kv_store/frameworks/innerkitsimpl/kvdb/src/task_executor.cpp b/kv_store/frameworks/innerkitsimpl/kvdb/src/task_executor.cpp index daec059e..fecdeac7 100644 --- a/kv_store/frameworks/innerkitsimpl/kvdb/src/task_executor.cpp +++ b/kv_store/frameworks/innerkitsimpl/kvdb/src/task_executor.cpp @@ -21,14 +21,21 @@ TaskExecutor &TaskExecutor::GetInstance() return instance; } -bool TaskExecutor::Execute(TaskScheduler::Task &&task, int32_t interval) +TaskScheduler::TaskId TaskExecutor::Execute(TaskScheduler::Task &&task, int32_t interval) { if (pool_ == nullptr) { - return false; + return TaskScheduler::INVALID_TASK_ID; } auto time = TaskScheduler::Clock::now() + std::chrono::milliseconds(interval); - pool_->At(time, std::move(task)); - return true; + return pool_->At(time, std::move(task)); +} + +void TaskExecutor::RemoveTask(TaskScheduler::TaskId taskId) +{ + if (pool_ == nullptr) { + return; + } + pool_->Remove(taskId, true); } TaskExecutor::TaskExecutor() diff --git a/kv_store/frameworks/innerkitsimpl/kvdb/test/single_store_impl_test.cpp b/kv_store/frameworks/innerkitsimpl/kvdb/test/single_store_impl_test.cpp index d71333e1..0722af98 100644 --- a/kv_store/frameworks/innerkitsimpl/kvdb/test/single_store_impl_test.cpp +++ b/kv_store/frameworks/innerkitsimpl/kvdb/test/single_store_impl_test.cpp @@ -29,13 +29,7 @@ namespace OHOS::Test { std::vector Random(int32_t len) { -// std::random_device randomDevice; -// std::uniform_int_distribution distribution(0, std::numeric_limits::max()); - std::vector key(len, 'a'); -// for (int32_t i = 0; i < len; i++) { -// key[i] = static_cast(distribution(randomDevice)); -// } - return key; + return std::vector(len, 'a'); } class SingleStoreImplTest : public testing::Test { @@ -921,7 +915,7 @@ HWTEST_F(SingleStoreImplTest, MaxLogSizeTest002, TestSize.Level0) auto status = kvStore_->GetResultSet({ "" }, output); ASSERT_EQ(status, SUCCESS); ASSERT_NE(output, nullptr); - ASSERT_GT(output->GetCount(), 0); + ASSERT_EQ(output->GetCount(), 3); EXPECT_EQ(output->MoveToFirst(), true); /** * @tc.steps:step3. Put more data into the database. diff --git a/kv_store/frameworks/innerkitsimpl/kvdb/test/store_factory_test.cpp b/kv_store/frameworks/innerkitsimpl/kvdb/test/store_factory_test.cpp index 8c96694e..7a14167b 100644 --- a/kv_store/frameworks/innerkitsimpl/kvdb/test/store_factory_test.cpp +++ b/kv_store/frameworks/innerkitsimpl/kvdb/test/store_factory_test.cpp @@ -66,9 +66,13 @@ public: static void DeleteKVStore(); }; -void StoreFactoryTest::SetUpTestCase(void){} +void StoreFactoryTest::SetUpTestCase(void) +{ +} -void StoreFactoryTest::TearDownTestCase(void){} +void StoreFactoryTest::TearDownTestCase(void) +{ +} void StoreFactoryTest::SetUp(void) { diff --git a/kv_store/frameworks/jskitsimpl/distributeddata/src/js_device_kv_store.cpp b/kv_store/frameworks/jskitsimpl/distributeddata/src/js_device_kv_store.cpp index d41f0cc4..a69f8c7a 100644 --- a/kv_store/frameworks/jskitsimpl/distributeddata/src/js_device_kv_store.cpp +++ b/kv_store/frameworks/jskitsimpl/distributeddata/src/js_device_kv_store.cpp @@ -286,6 +286,8 @@ napi_value JsDeviceKVStore::GetResultSet(napi_env env, napi_callback_info info) ctxt->status = (status == Status::SUCCESS) ? napi_ok : napi_generic_failure; CHECK_STATUS_RETURN_VOID(ctxt, "kvStore->GetResultSet() failed!"); ctxt->resultSet->SetNative(kvResultSet); + bool isSchema = reinterpret_cast(ctxt->native)->IsSchemaStore(); + ctxt->resultSet->SetSchema(isSchema); }; auto output = [env, ctxt](napi_value& result) { ctxt->status = napi_get_reference_value(env, ctxt->ref, &result); diff --git a/kv_store/frameworks/jskitsimpl/distributeddata/src/js_kv_manager.cpp b/kv_store/frameworks/jskitsimpl/distributeddata/src/js_kv_manager.cpp index defda843..ff9d3027 100644 --- a/kv_store/frameworks/jskitsimpl/distributeddata/src/js_kv_manager.cpp +++ b/kv_store/frameworks/jskitsimpl/distributeddata/src/js_kv_manager.cpp @@ -152,6 +152,7 @@ napi_value JsKVManager::GetKVStore(napi_env env, napi_callback_info info) CHECK_STATUS_RETURN_VOID(ctxt, "output get ref value failed"); ctxt->status = napi_delete_reference(env, ctxt->ref); CHECK_STATUS_RETURN_VOID(ctxt, "output del ref failed"); + ZLOGI("output del ref success"); }; return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute, output); } diff --git a/kv_store/frameworks/jskitsimpl/distributeddata/src/js_single_kv_store.cpp b/kv_store/frameworks/jskitsimpl/distributeddata/src/js_single_kv_store.cpp index 504b3eb7..bf01fe48 100644 --- a/kv_store/frameworks/jskitsimpl/distributeddata/src/js_single_kv_store.cpp +++ b/kv_store/frameworks/jskitsimpl/distributeddata/src/js_single_kv_store.cpp @@ -236,6 +236,8 @@ napi_value JsSingleKVStore::GetResultSet(napi_env env, napi_callback_info info) ctxt->status = (status == Status::SUCCESS) ? napi_ok : napi_generic_failure; CHECK_STATUS_RETURN_VOID(ctxt, "kvStore->GetResultSet() failed!"); ctxt->resultSet->SetNative(kvResultSet); + bool isSchema = reinterpret_cast(ctxt->native)->IsSchemaStore(); + ctxt->resultSet->SetSchema(isSchema); }; auto output = [env, ctxt](napi_value& result) { ctxt->status = napi_get_reference_value(env, ctxt->ref, &result); diff --git a/kv_store/frameworks/jskitsimpl/distributedkvstore/src/js_device_kv_store.cpp b/kv_store/frameworks/jskitsimpl/distributedkvstore/src/js_device_kv_store.cpp index 829be592..c3ea9f58 100644 --- a/kv_store/frameworks/jskitsimpl/distributedkvstore/src/js_device_kv_store.cpp +++ b/kv_store/frameworks/jskitsimpl/distributedkvstore/src/js_device_kv_store.cpp @@ -54,6 +54,8 @@ napi_value JsDeviceKVStore::Constructor(napi_env env) DECLARE_NAPI_FUNCTION("rollback", JsSingleKVStore::Rollback), DECLARE_NAPI_FUNCTION("enableSync", JsSingleKVStore::EnableSync), DECLARE_NAPI_FUNCTION("setSyncRange", JsSingleKVStore::SetSyncRange), + DECLARE_NAPI_FUNCTION("backup", JsSingleKVStore::Backup), + DECLARE_NAPI_FUNCTION("restore", JsSingleKVStore::Restore), /* JsDeviceKVStore externs JsSingleKVStore */ DECLARE_NAPI_FUNCTION("get", JsDeviceKVStore::Get), DECLARE_NAPI_FUNCTION("getEntries", JsDeviceKVStore::GetEntries), @@ -252,6 +254,8 @@ napi_value JsDeviceKVStore::GetResultSet(napi_env env, napi_callback_info info) ctxt->status = (GenerateNapiError(status, ctxt->jsCode, ctxt->error) == Status::SUCCESS) ? napi_ok : napi_generic_failure; ctxt->resultSet->SetKvStoreResultSetPtr(kvResultSet); + bool isSchema = reinterpret_cast(ctxt->native)->IsSchemaStore(); + ctxt->resultSet->SetSchema(isSchema); }; auto output = [env, ctxt](napi_value& result) { ctxt->status = napi_get_reference_value(env, ctxt->ref, &result); diff --git a/kv_store/frameworks/jskitsimpl/distributedkvstore/src/js_error_utils.cpp b/kv_store/frameworks/jskitsimpl/distributedkvstore/src/js_error_utils.cpp index 7904735d..2e3f5031 100644 --- a/kv_store/frameworks/jskitsimpl/distributedkvstore/src/js_error_utils.cpp +++ b/kv_store/frameworks/jskitsimpl/distributedkvstore/src/js_error_utils.cpp @@ -30,8 +30,9 @@ static constexpr JsErrorCode JS_ERROR_CODE_MSGS[] = { { Status::STORE_META_CHANGED, 15100002, "Open existed database with changed options." }, { Status::PERMISSION_DENIED, 202, "Permission denied" }, { Status::CRYPT_ERROR, 15100003, "Database corrupted." }, - { Status::OVER_MAX_LIMITS, 15100001, "Over max subscribe limits." }, + { Status::OVER_MAX_LIMITS, 15100001, "Over max limits." }, { Status::ALREADY_CLOSED, 15100005, "Database or result set already closed." }, + { Status::WAL_OVER_LIMITS, 14800047, "the WAL file size exceeds the default limit."} }; const std::optional GetJsErrorCode(int32_t errorCode) diff --git a/kv_store/frameworks/jskitsimpl/distributedkvstore/src/js_kv_manager.cpp b/kv_store/frameworks/jskitsimpl/distributedkvstore/src/js_kv_manager.cpp index 4870603c..091f131e 100644 --- a/kv_store/frameworks/jskitsimpl/distributedkvstore/src/js_kv_manager.cpp +++ b/kv_store/frameworks/jskitsimpl/distributedkvstore/src/js_kv_manager.cpp @@ -159,6 +159,7 @@ napi_value JsKVManager::GetKVStore(napi_env env, napi_callback_info info) ctxt->status = napi_get_reference_value(env, ctxt->ref, &result); napi_delete_reference(env, ctxt->ref); ASSERT_STATUS(ctxt, "output KVManager failed"); + ZLOGI("output delete reference success"); }; return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute, output); } @@ -327,7 +328,6 @@ napi_value JsKVManager::Off(napi_env env, napi_callback_info info) auto ctxt = std::make_shared(); auto input = [env, ctxt](size_t argc, napi_value* argv) { // required 1 or 2 arguments :: [callback] - // ASSERT_ARGS(ctxt, (argc == 1) || (argc == 2), "invalid arguments!"); ASSERT_BUSINESS_ERR(ctxt, argc > 0, Status::INVALID_ARGUMENT, "The number of parameters is incorrect."); std::string event; ctxt->status = JSUtil::GetValue(env, argv[0], event); diff --git a/kv_store/frameworks/jskitsimpl/distributedkvstore/src/js_single_kv_store.cpp b/kv_store/frameworks/jskitsimpl/distributedkvstore/src/js_single_kv_store.cpp index 138bab26..8320919f 100644 --- a/kv_store/frameworks/jskitsimpl/distributedkvstore/src/js_single_kv_store.cpp +++ b/kv_store/frameworks/jskitsimpl/distributedkvstore/src/js_single_kv_store.cpp @@ -1008,6 +1008,8 @@ napi_value JsSingleKVStore::GetResultSet(napi_env env, napi_callback_info info) ctxt->status = (GenerateNapiError(status, ctxt->jsCode, ctxt->error) == Status::SUCCESS) ? napi_ok : napi_generic_failure; ctxt->resultSet->SetKvStoreResultSetPtr(kvResultSet); + bool isSchema = reinterpret_cast(ctxt->native)->IsSchemaStore(); + ctxt->resultSet->SetSchema(isSchema); }; auto output = [env, ctxt](napi_value& result) { ctxt->status = napi_get_reference_value(env, ctxt->ref, &result); diff --git a/kv_store/frameworks/libs/distributeddb/BUILD.gn b/kv_store/frameworks/libs/distributeddb/BUILD.gn index 7f8451d2..cf7b051d 100644 --- a/kv_store/frameworks/libs/distributeddb/BUILD.gn +++ b/kv_store/frameworks/libs/distributeddb/BUILD.gn @@ -50,6 +50,7 @@ config("distrdb_config") { "SQLITE_DISTRIBUTE_RELATIONAL", "USE_DFX_ABILITY", "SQLITE_ENABLE_DROPTABLE_CALLBACK", + "OPENSSL_SUPPRESS_DEPRECATED", ] if (is_debug) { defines += [ "TRACE_SQLITE_EXECUTE" ] diff --git a/kv_store/frameworks/libs/distributeddb/common/include/db_common.h b/kv_store/frameworks/libs/distributeddb/common/include/db_common.h index c4398105..24217cd5 100644 --- a/kv_store/frameworks/libs/distributeddb/common/include/db_common.h +++ b/kv_store/frameworks/libs/distributeddb/common/include/db_common.h @@ -60,6 +60,13 @@ public: static std::string GetDistributedTableName(const std::string &device, const std::string &tableName); + static std::string GetDistributedTableName(const std::string &device, const std::string &tableName, + const StoreInfo &info); + + static std::string GetDistributedTableNameWithHash(const std::string &device, const std::string &tableName); + + static std::string CalDistributedTableName(const std::string &device, const std::string &tableName); + static void GetDeviceFromName(const std::string &deviceTableName, std::string &deviceHash, std::string &tableName); static std::string TrimSpace(const std::string &input); diff --git a/kv_store/frameworks/libs/distributeddb/common/include/db_constant.h b/kv_store/frameworks/libs/distributeddb/common/include/db_constant.h index 928a0865..e593bd3f 100644 --- a/kv_store/frameworks/libs/distributeddb/common/include/db_constant.h +++ b/kv_store/frameworks/libs/distributeddb/common/include/db_constant.h @@ -159,6 +159,8 @@ public: static constexpr uint32_t MAX_CONDITION_COUNT = 32; static constexpr uint32_t REMOTE_QUERY_MAX_SQL_LEN = 1000000U; + + static constexpr int HASH_KEY_SIZE = 32; // size of SHA256_DIGEST_LENGTH }; } // namespace DistributedDB #endif // DISTRIBUTEDDB_CONSTANT_H diff --git a/kv_store/frameworks/libs/distributeddb/common/include/db_errno.h b/kv_store/frameworks/libs/distributeddb/common/include/db_errno.h index 13a1098c..716689d2 100644 --- a/kv_store/frameworks/libs/distributeddb/common/include/db_errno.h +++ b/kv_store/frameworks/libs/distributeddb/common/include/db_errno.h @@ -125,6 +125,7 @@ constexpr int E_NONEXISTENT = (E_BASE + 103); // for result set, nonexistent in constexpr int E_TYPE_MISMATCH = (E_BASE + 104); // for result set, mismatch type constexpr int E_DENIED_SQL = (E_BASE + 105); // denied sql, not permit to execute constexpr int E_USER_CHANGE = (E_BASE + 106); // user change +constexpr int E_CONSTRAINT = (E_BASE + 107); // sql failed with constraint // Num 150+ is reserved for schema related errno, since it may be added regularly constexpr int E_JSON_PARSE_FAIL = (E_BASE + 150); // Parse json fail in grammatical level constexpr int E_JSON_INSERT_PATH_EXIST = (E_BASE + 151); // Path already exist before insert diff --git a/kv_store/frameworks/libs/distributeddb/common/include/db_types.h b/kv_store/frameworks/libs/distributeddb/common/include/db_types.h index e553ddcb..6b836a6f 100644 --- a/kv_store/frameworks/libs/distributeddb/common/include/db_types.h +++ b/kv_store/frameworks/libs/distributeddb/common/include/db_types.h @@ -157,8 +157,8 @@ enum DistributedTableMode : int { struct CaseInsensitiveComparator { bool operator() (const std::string& first, const std::string& second) const { - std::string str1(first.length(),' '); - std::string str2(second.length(),' '); + std::string str1(first.length(), ' '); + std::string str2(second.length(), ' '); std::transform(first.begin(), first.end(), str1.begin(), tolower); std::transform(second.begin(), second.end(), str2.begin(), tolower); return str1 < str2; diff --git a/kv_store/frameworks/libs/distributeddb/common/include/runtime_context.h b/kv_store/frameworks/libs/distributeddb/common/include/runtime_context.h index 856c5b31..115ba706 100644 --- a/kv_store/frameworks/libs/distributeddb/common/include/runtime_context.h +++ b/kv_store/frameworks/libs/distributeddb/common/include/runtime_context.h @@ -141,6 +141,13 @@ public: virtual void StopTaskPool() = 0; virtual void StopTimeTickMonitorIfNeed() = 0; + + virtual void SetTranslateToDeviceIdCallback(const TranslateToDeviceIdCallback &callback) = 0; + + virtual int TranslateDeviceId(const std::string &deviceId, + const StoreInfo &info, std::string &newDeviceId) = 0; + + virtual bool ExistTranslateDevIdCallback() const = 0; protected: RuntimeContext() = default; virtual ~RuntimeContext() {} diff --git a/kv_store/frameworks/libs/distributeddb/common/src/auto_launch.cpp b/kv_store/frameworks/libs/distributeddb/common/src/auto_launch.cpp index da7c4e6f..cb0b4745 100644 --- a/kv_store/frameworks/libs/distributeddb/common/src/auto_launch.cpp +++ b/kv_store/frameworks/libs/distributeddb/common/src/auto_launch.cpp @@ -34,6 +34,7 @@ namespace DistributedDB { namespace { constexpr int MAX_AUTO_LAUNCH_ITEM_NUM = 8; + const char *AUTO_LAUNCH_ID = "AutoLaunchID"; } void AutoLaunch::SetCommunicatorAggregator(ICommunicatorAggregator *aggregator) @@ -1029,6 +1030,7 @@ int AutoLaunch::GetAutoLaunchRelationProperties(const AutoLaunchParam ¶m, } propertiesPtr->SetCipherArgs(param.option.cipher, param.option.passwd, param.option.iterateTimes); } + propertiesPtr->SetIntProp(AUTO_LAUNCH_ID, static_cast(RuntimeContext::GetInstance()->GenerateSessionId())); return E_OK; } @@ -1296,14 +1298,26 @@ void AutoLaunch::CloseConnection(DBType type, const DBProperties &properties) return; } std::string identifier = properties.GetStringProp(DBProperties::IDENTIFIER_DATA, ""); - std::lock_guard lock(dataLock_); + int closeId = properties.GetIntProp(AUTO_LAUNCH_ID, 0); + std::lock_guard lock(extLock_); auto itemMapIter = extItemMap_.find(identifier); if (itemMapIter == extItemMap_.end()) { + LOGD("[AutoLaunch] Abort close because not found id"); return; } std::string userId = properties.GetStringProp(DBProperties::USER_ID, ""); auto itemIter = itemMapIter->second.find(userId); if (itemIter == itemMapIter->second.end()) { + LOGD("[AutoLaunch] Abort close because not found user id"); + return; + } + if (itemIter->second.propertiesPtr == nullptr) { + LOGD("[AutoLaunch] Abort close because properties is invalid"); + return; + } + int targetId = itemIter->second.propertiesPtr->GetIntProp(AUTO_LAUNCH_ID, 0); + if (closeId != targetId) { + LOGD("[AutoLaunch] Abort close because connection has been closed"); return; } TryCloseConnection(itemIter->second); diff --git a/kv_store/frameworks/libs/distributeddb/common/src/data_value.cpp b/kv_store/frameworks/libs/distributeddb/common/src/data_value.cpp index 99fc897d..6ac0ad91 100644 --- a/kv_store/frameworks/libs/distributeddb/common/src/data_value.cpp +++ b/kv_store/frameworks/libs/distributeddb/common/src/data_value.cpp @@ -175,7 +175,7 @@ DataValue &DataValue::operator=(const Blob &blob) int DataValue::Set(Blob *&blob) { ResetValue(); - if (blob == nullptr || blob->GetSize() <= 0) { + if (blob == nullptr || blob->GetSize() < 0) { LOGE("Transfer Blob to DataValue failed."); return -E_INVALID_ARGS; } @@ -257,7 +257,7 @@ int DataValue::GetBlob(Blob *&outVal) const int DataValue::SetBlob(const Blob &val) { ResetValue(); - if (val.GetSize() <= 0) { + if (val.GetSize() < 0) { return E_OK; } value_.blobPtr = new(std::nothrow) Blob(); diff --git a/kv_store/frameworks/libs/distributeddb/common/src/db_common.cpp b/kv_store/frameworks/libs/distributeddb/common/src/db_common.cpp index 74bf012f..ee39d9ce 100644 --- a/kv_store/frameworks/libs/distributeddb/common/src/db_common.cpp +++ b/kv_store/frameworks/libs/distributeddb/common/src/db_common.cpp @@ -21,6 +21,7 @@ #include "db_errno.h" #include "platform_specific.h" #include "hash.h" +#include "runtime_context.h" #include "value_hash_calc.h" namespace DistributedDB { @@ -321,9 +322,32 @@ std::string DBCommon::StringMasking(const std::string &oriStr, size_t remain) } std::string DBCommon::GetDistributedTableName(const std::string &device, const std::string &tableName) +{ + if (!RuntimeContext::GetInstance()->ExistTranslateDevIdCallback()) { + return GetDistributedTableNameWithHash(device, tableName); + } + return CalDistributedTableName(device, tableName); +} + +std::string DBCommon::GetDistributedTableName(const std::string &device, const std::string &tableName, + const StoreInfo &info) +{ + std::string newDeviceId; + if (RuntimeContext::GetInstance()->TranslateDeviceId(device, info, newDeviceId) != E_OK) { + return GetDistributedTableNameWithHash(device, tableName); + } + return CalDistributedTableName(newDeviceId, tableName); +} + +std::string DBCommon::GetDistributedTableNameWithHash(const std::string &device, const std::string &tableName) { std::string deviceHashHex = DBCommon::TransferStringToHex(DBCommon::TransferHashString(device)); - return DBConstant::RELATIONAL_PREFIX + tableName + "_" + deviceHashHex; + return CalDistributedTableName(deviceHashHex, tableName); +} + +std::string DBCommon::CalDistributedTableName(const std::string &device, const std::string &tableName) +{ + return DBConstant::RELATIONAL_PREFIX + tableName + "_" + device; } void DBCommon::GetDeviceFromName(const std::string &deviceTableName, std::string &deviceHash, std::string &tableName) diff --git a/kv_store/frameworks/libs/distributeddb/common/src/runtime_context_impl.cpp b/kv_store/frameworks/libs/distributeddb/common/src/runtime_context_impl.cpp index 9fe505aa..dd39f1db 100644 --- a/kv_store/frameworks/libs/distributeddb/common/src/runtime_context_impl.cpp +++ b/kv_store/frameworks/libs/distributeddb/common/src/runtime_context_impl.cpp @@ -14,6 +14,7 @@ */ #include "runtime_context_impl.h" +#include "db_common.h" #include "db_errno.h" #include "db_dfx_adapter.h" #include "log_print.h" @@ -746,4 +747,33 @@ void RuntimeContextImpl::StopTimeTickMonitorIfNeed() timeTickMonitor_ = nullptr; } } + +void RuntimeContextImpl::SetTranslateToDeviceIdCallback(const TranslateToDeviceIdCallback &callback) +{ + std::lock_guard autoLock(translateToDeviceIdLock_); + translateToDeviceIdCallback_ = callback; + deviceIdCache_.clear(); +} + +int RuntimeContextImpl::TranslateDeviceId(const std::string &deviceId, + const StoreInfo &info, std::string &newDeviceId) +{ + const std::string id = DBCommon::GenerateIdentifierId(info.storeId, info.appId, info.userId); + std::lock_guard autoLock(translateToDeviceIdLock_); + if (translateToDeviceIdCallback_ == nullptr) { + return -E_NOT_SUPPORT; + } + if (deviceIdCache_.find(deviceId) == deviceIdCache_.end() || + deviceIdCache_[deviceId].find(id) == deviceIdCache_[deviceId].end()) { + deviceIdCache_[deviceId][id] = translateToDeviceIdCallback_(deviceId, info); + } + newDeviceId = deviceIdCache_[deviceId][id]; + return E_OK; +} + +bool RuntimeContextImpl::ExistTranslateDevIdCallback() const +{ + std::lock_guard autoLock(translateToDeviceIdLock_); + return translateToDeviceIdCallback_ != nullptr; +} } // namespace DistributedDB diff --git a/kv_store/frameworks/libs/distributeddb/common/src/runtime_context_impl.h b/kv_store/frameworks/libs/distributeddb/common/src/runtime_context_impl.h index 62b9ce62..6ed8218b 100644 --- a/kv_store/frameworks/libs/distributeddb/common/src/runtime_context_impl.h +++ b/kv_store/frameworks/libs/distributeddb/common/src/runtime_context_impl.h @@ -130,6 +130,12 @@ public: void StopTimeTickMonitorIfNeed() override; + void SetTranslateToDeviceIdCallback(const TranslateToDeviceIdCallback &callback) override; + + int TranslateDeviceId(const std::string &deviceId, + const StoreInfo &info, std::string &newDeviceId) override; + + bool ExistTranslateDevIdCallback() const override; private: static constexpr int MAX_TP_THREADS = 10; // max threads of the task pool. static constexpr int MIN_TP_THREADS = 1; // min threads of the task pool. @@ -192,6 +198,10 @@ private: // Get map from this callback, use for run permission check in remote device mutable std::shared_mutex permissionConditionLock_; PermissionConditionCallback permissionConditionCallback_; + + mutable std::mutex translateToDeviceIdLock_; + TranslateToDeviceIdCallback translateToDeviceIdCallback_; + std::map> deviceIdCache_; // cache > }; } // namespace DistributedDB diff --git a/kv_store/frameworks/libs/distributeddb/communicator/src/communicator_aggregator.cpp b/kv_store/frameworks/libs/distributeddb/communicator/src/communicator_aggregator.cpp index 3cb9f9aa..4f8427e1 100644 --- a/kv_store/frameworks/libs/distributeddb/communicator/src/communicator_aggregator.cpp +++ b/kv_store/frameworks/libs/distributeddb/communicator/src/communicator_aggregator.cpp @@ -405,6 +405,17 @@ void CommunicatorAggregator::SendPacketsAndDisposeTask(const SendTask &inTask, break; } } + if (errCode == -E_WAIT_RETRY) { + const int RETRY_INTERVAL = 1000; + TimerId timerId = 0u; + const std::string target = inTask.dstTarget; + RefObject::IncObjRef(this); + errCode = RuntimeContext::GetInstance()->SetTimer(RETRY_INTERVAL, [this, target](TimerId id) { + OnSendable(target); + RefObject::DecObjRef(this); + return -E_END_TIMER; + }, nullptr, timerId); + } if (taskNeedFinalize) { TaskFinalizer(inTask, errCode); } diff --git a/kv_store/frameworks/libs/distributeddb/communicator/src/network_adapter.cpp b/kv_store/frameworks/libs/distributeddb/communicator/src/network_adapter.cpp index 921a3732..849bae84 100644 --- a/kv_store/frameworks/libs/distributeddb/communicator/src/network_adapter.cpp +++ b/kv_store/frameworks/libs/distributeddb/communicator/src/network_adapter.cpp @@ -214,6 +214,10 @@ int NetworkAdapter::SendBytes(const std::string &dstTarget, const uint8_t *bytes DeviceInfos dstDevInfo; dstDevInfo.identifier = dstTarget; DBStatus errCode = processCommunicator_->SendData(dstDevInfo, bytes, length); + if (errCode == DBStatus::RATE_LIMIT) { + LOGD("[NAdapt][SendBytes] rate limit!"); + return -E_WAIT_RETRY; + } if (errCode != DBStatus::OK) { LOGE("[NAdapt][SendBytes] SendData Fail, errCode=%d.", static_cast(errCode)); // These code is compensation for the probable defect of IProcessCommunicator implementation. diff --git a/kv_store/frameworks/libs/distributeddb/communicator/src/protocol_proto.cpp b/kv_store/frameworks/libs/distributeddb/communicator/src/protocol_proto.cpp index 5268d291..c7859716 100644 --- a/kv_store/frameworks/libs/distributeddb/communicator/src/protocol_proto.cpp +++ b/kv_store/frameworks/libs/distributeddb/communicator/src/protocol_proto.cpp @@ -24,6 +24,7 @@ #include "macro_utils.h" #include "securec.h" #include "version.h" +#include namespace DistributedDB { namespace { @@ -60,6 +61,7 @@ FrameType GetFrameType(uint8_t inPacketType) } std::map ProtocolProto::msgIdMapFunc_; +std::shared_mutex ProtocolProto::msgIdMutex_; uint32_t ProtocolProto::GetAppLayerFrameHeaderLength() { @@ -366,6 +368,7 @@ int ProtocolProto::CombinePacketIntoFrame(SerialBuffer *inFrame, const uint8_t * int ProtocolProto::RegTransformFunction(uint32_t msgId, const TransformFunc &inFunc) { + std::unique_lock autoLock(msgIdMutex_); if (msgIdMapFunc_.count(msgId) != 0) { return -E_ALREADY_REGISTER; } @@ -378,6 +381,7 @@ int ProtocolProto::RegTransformFunction(uint32_t msgId, const TransformFunc &inF void ProtocolProto::UnRegTransformFunction(uint32_t msgId) { + std::unique_lock autoLock(msgIdMutex_); if (msgIdMapFunc_.count(msgId) != 0) { msgIdMapFunc_.erase(msgId); } @@ -582,12 +586,12 @@ int ProtocolProto::CalculateXorSum(const uint8_t *bytes, uint32_t length, uint64 int ProtocolProto::CalculateDataSerializeLength(const Message *inMsg, uint32_t &outLength) { uint32_t messageId = inMsg->GetMessageId(); - if (msgIdMapFunc_.count(messageId) == 0) { + TransformFunc function; + if (GetTransformFunc(messageId, function) != E_OK) { LOGE("[Proto][CalcuDataSerialLen] Not registered for messageId=%" PRIu32 ".", messageId); return -E_NOT_REGISTER; } - TransformFunc function = msgIdMapFunc_[messageId]; uint32_t serializeLen = function.computeFunc(inMsg); uint32_t alignedLen = BYTE_8_ALIGN(serializeLen); // Currently not allowed the upper module to send a message without data. Regard serializeLen zero as abnormal. @@ -625,8 +629,11 @@ int ProtocolProto::SerializeMessage(SerialBuffer *inBuff, const Message *inMsg) return E_OK; } // If dataLen not zero, the TransformFunc of this messageId must exist, the caller's logic guarantee it - uint32_t messageId = inMsg->GetMessageId(); - TransformFunc function = msgIdMapFunc_[messageId]; + TransformFunc function; + if (GetTransformFunc(inMsg->GetMessageId(), function) != E_OK) { + LOGE("[Proto][Serialize] Not register, messageId=%" PRIu32 ".", inMsg->GetMessageId()); + return -E_NOT_REGISTER; + } int result = function.serializeFunc(payloadByteLen.first + sizeof(MessageHeader), dataLen, inMsg); if (result != E_OK) { LOGE("[Proto][Serialize] SerializeFunc Fail, result=%d.", result); @@ -674,12 +681,11 @@ int ProtocolProto::DeSerializeMessage(const SerialBuffer *inBuff, Message *inMsg if (onlyMsgHeader || dataLen == 0) { // Do not need to deserialize data return E_OK; } - uint32_t messageId = inMsg->GetMessageId(); - if (msgIdMapFunc_.count(messageId) == 0) { - LOGE("[Proto][DeSerialize] Not register, messageId=%" PRIu32 ".", messageId); + TransformFunc function; + if (GetTransformFunc(inMsg->GetMessageId(), function) != E_OK) { + LOGE("[Proto][DeSerialize] Not register, messageId=%" PRIu32 ".", inMsg->GetMessageId()); return -E_NOT_REGISTER; } - TransformFunc function = msgIdMapFunc_[messageId]; int result = function.deserializeFunc(payloadByteLen.first + sizeof(MessageHeader), dataLen, inMsg); if (result != E_OK) { LOGE("[Proto][DeSerialize] DeserializeFunc Fail, result=%d.", result); @@ -723,11 +729,6 @@ int ProtocolProto::ParseCommPhyHeaderCheckMagicAndVersion(const uint8_t *bytes, int ProtocolProto::ParseCommPhyHeaderCheckField(const std::string &srcTarget, const CommPhyHeader &phyHeader, const uint8_t *bytes, uint32_t length) { - if (phyHeader.sourceId != Hash::HashFunc(srcTarget)) { - LOGE("[Proto][ParsePhyCheck] SourceId Error: inSourceId=%" PRIu64 ", srcTarget=%s{private}, hashId=%" PRIu64, - ULL(phyHeader.sourceId), srcTarget.c_str(), ULL(Hash::HashFunc(srcTarget))); - return -E_PARSE_FAIL; - } if (phyHeader.packetLen != length) { LOGE("[Proto][ParsePhyCheck] PacketLen=%" PRIu32 " Mismatch length=%" PRIu32 ".", phyHeader.packetLen, length); return -E_PARSE_FAIL; @@ -1092,4 +1093,15 @@ int ProtocolProto::FillExtendHeadDataIfNeed(std::shared_ptr } return E_OK; } + +int ProtocolProto::GetTransformFunc(uint32_t messageId, DistributedDB::TransformFunc &function) +{ + std::shared_lock autoLock(msgIdMutex_); + const auto &entry = msgIdMapFunc_.find(messageId); + if (entry == msgIdMapFunc_.end()) { + return -E_NOT_REGISTER; + } + function = entry->second; + return E_OK; +} } // namespace DistributedDB diff --git a/kv_store/frameworks/libs/distributeddb/communicator/src/protocol_proto.h b/kv_store/frameworks/libs/distributeddb/communicator/src/protocol_proto.h index c5f7e091..f151f0a6 100644 --- a/kv_store/frameworks/libs/distributeddb/communicator/src/protocol_proto.h +++ b/kv_store/frameworks/libs/distributeddb/communicator/src/protocol_proto.h @@ -18,6 +18,7 @@ #include #include +#include #include "communicator_type_define.h" #include "frame_header.h" #include "iprocess_communicator.h" @@ -130,6 +131,9 @@ private: static int FillExtendHeadDataIfNeed(std::shared_ptr &extendHandle, SerialBuffer *buffer, uint32_t headSize); + static int GetTransformFunc(uint32_t messageId, TransformFunc &function); + + static std::shared_mutex msgIdMutex_; static std::map msgIdMapFunc_; }; } // namespace DistributedDB diff --git a/kv_store/frameworks/libs/distributeddb/distributeddb.gni b/kv_store/frameworks/libs/distributeddb/distributeddb.gni index a6e2c588..87c4b466 100644 --- a/kv_store/frameworks/libs/distributeddb/distributeddb.gni +++ b/kv_store/frameworks/libs/distributeddb/distributeddb.gni @@ -145,6 +145,7 @@ distributeddb_src = [ "${distributeddb_path}/storage/src/sqlite/sqlite_local_storage_engine.cpp", "${distributeddb_path}/storage/src/sqlite/sqlite_local_storage_executor.cpp", "${distributeddb_path}/storage/src/sqlite/sqlite_log_table_manager.cpp", + "${distributeddb_path}/storage/src/sqlite/sqlite_meta_executor.cpp", "${distributeddb_path}/storage/src/sqlite/sqlite_multi_ver_data_storage.cpp", "${distributeddb_path}/storage/src/sqlite/sqlite_multi_ver_transaction.cpp", "${distributeddb_path}/storage/src/sqlite/sqlite_query_helper.cpp", diff --git a/kv_store/frameworks/libs/distributeddb/include/types_export.h b/kv_store/frameworks/libs/distributeddb/include/types_export.h index 95adef5e..9772f2a8 100644 --- a/kv_store/frameworks/libs/distributeddb/include/types_export.h +++ b/kv_store/frameworks/libs/distributeddb/include/types_export.h @@ -206,5 +206,12 @@ enum class CompressAlgorithm : uint8_t { NONE = 0, ZLIB = 1 }; + +struct StoreInfo { + std::string userId; + std::string appId; + std::string storeId; +}; +using TranslateToDeviceIdCallback = std::function; } // namespace DistributedDB #endif // DISTRIBUTEDDB_TYPES_EXPORT_H diff --git a/kv_store/frameworks/libs/distributeddb/interfaces/include/kv_store_nb_delegate.h b/kv_store/frameworks/libs/distributeddb/interfaces/include/kv_store_nb_delegate.h index 21a11218..453aea70 100644 --- a/kv_store/frameworks/libs/distributeddb/interfaces/include/kv_store_nb_delegate.h +++ b/kv_store/frameworks/libs/distributeddb/interfaces/include/kv_store_nb_delegate.h @@ -227,6 +227,9 @@ public: // calculate full sync sync data size after Serialize; // return 1M while sync data size is larger than 1M, otherwise return actualy size DB_API virtual size_t GetSyncDataSize(const std::string &device) const = 0; + + // update all key in sync_data which is not deleted data + DB_API virtual DBStatus UpdateKey(const UpdateKeyCallback &callback) = 0; }; } // namespace DistributedDB diff --git a/kv_store/frameworks/libs/distributeddb/interfaces/include/relational/relational_store_delegate.h b/kv_store/frameworks/libs/distributeddb/interfaces/include/relational/relational_store_delegate.h index 9bb6f38e..3405f055 100644 --- a/kv_store/frameworks/libs/distributeddb/interfaces/include/relational/relational_store_delegate.h +++ b/kv_store/frameworks/libs/distributeddb/interfaces/include/relational/relational_store_delegate.h @@ -50,6 +50,9 @@ public: // timeout is in ms. DB_API virtual DBStatus RemoteQuery(const std::string &device, const RemoteCondition &condition, uint64_t timeout, std::shared_ptr &result) = 0; + + // remove all device data + DB_API virtual DBStatus RemoveDeviceData() = 0; }; } // namespace DistributedDB #endif // RELATIONAL_STORE_DELEGATE_H \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/interfaces/include/runtime_config.h b/kv_store/frameworks/libs/distributeddb/interfaces/include/runtime_config.h index 1386e474..5bbd98fb 100644 --- a/kv_store/frameworks/libs/distributeddb/interfaces/include/runtime_config.h +++ b/kv_store/frameworks/libs/distributeddb/interfaces/include/runtime_config.h @@ -50,6 +50,7 @@ public: DB_API static bool IsProcessSystemApiAdapterValid(); + DB_API static void SetTranslateToDeviceIdCallback(const TranslateToDeviceIdCallback &callback); private: static std::mutex communicatorMutex_; static std::mutex multiUserMutex_; diff --git a/kv_store/frameworks/libs/distributeddb/interfaces/include/store_types.h b/kv_store/frameworks/libs/distributeddb/interfaces/include/store_types.h index 1fc0b12e..21f693ed 100644 --- a/kv_store/frameworks/libs/distributeddb/interfaces/include/store_types.h +++ b/kv_store/frameworks/libs/distributeddb/interfaces/include/store_types.h @@ -65,6 +65,9 @@ enum DBStatus { NONEXISTENT, // for row record, pass invalid column name or invalid column index. TYPE_MISMATCH, // for row record, get value with mismatch func. REMOTE_OVER_SIZE, // for remote query, the data is too many, only get part or data. + RATE_LIMIT, + DATA_HANDLE_ERROR, // remote handle data failed + CONSTRAINT, // constraint check failed in sqlite }; struct KvStoreConfig { @@ -128,5 +131,7 @@ struct RemoteCondition { std::string sql; // The sql statement; std::vector bindArgs; // The bind args. }; + +using UpdateKeyCallback = std::function; } // namespace DistributedDB #endif // KV_STORE_TYPE_H diff --git a/kv_store/frameworks/libs/distributeddb/interfaces/src/kv_store_errno.cpp b/kv_store/frameworks/libs/distributeddb/interfaces/src/kv_store_errno.cpp index 3128f46f..94305280 100644 --- a/kv_store/frameworks/libs/distributeddb/interfaces/src/kv_store_errno.cpp +++ b/kv_store/frameworks/libs/distributeddb/interfaces/src/kv_store_errno.cpp @@ -66,6 +66,7 @@ namespace { { -E_FEEDBACK_UNKNOWN_MESSAGE, NOT_SUPPORT }, { -E_NOT_PERMIT, PERMISSION_CHECK_FORBID_SYNC }, { -E_REMOTE_OVER_SIZE, OVER_MAX_LIMITS }, + { -E_CONSTRAINT, CONSTRAINT }, }; } diff --git a/kv_store/frameworks/libs/distributeddb/interfaces/src/kv_store_nb_delegate_impl.cpp b/kv_store/frameworks/libs/distributeddb/interfaces/src/kv_store_nb_delegate_impl.cpp index 4f453178..9a8f4772 100644 --- a/kv_store/frameworks/libs/distributeddb/interfaces/src/kv_store_nb_delegate_impl.cpp +++ b/kv_store/frameworks/libs/distributeddb/interfaces/src/kv_store_nb_delegate_impl.cpp @@ -974,4 +974,22 @@ size_t KvStoreNbDelegateImpl::GetSyncDataSize(const std::string &device) const } return size; } + +DBStatus KvStoreNbDelegateImpl::UpdateKey(const UpdateKeyCallback &callback) +{ + if (conn_ == nullptr) { + LOGE("%s", INVALID_CONNECTION); + return DB_ERROR; + } + if (callback == nullptr) { + return INVALID_ARGS; + } + int errCode = conn_->UpdateKey(callback); + if (errCode == E_OK) { + LOGI("[KvStoreNbDelegate] update keys success"); + return OK; + } + LOGW("[KvStoreNbDelegate] update keys failed:%d", errCode); + return TransferDBErrno(errCode); +} } // namespace DistributedDB diff --git a/kv_store/frameworks/libs/distributeddb/interfaces/src/kv_store_nb_delegate_impl.h b/kv_store/frameworks/libs/distributeddb/interfaces/src/kv_store_nb_delegate_impl.h index 7ca51a31..24d7c5d8 100644 --- a/kv_store/frameworks/libs/distributeddb/interfaces/src/kv_store_nb_delegate_impl.h +++ b/kv_store/frameworks/libs/distributeddb/interfaces/src/kv_store_nb_delegate_impl.h @@ -156,6 +156,8 @@ public: size_t GetSyncDataSize(const std::string &device) const override; + // update all key in sync_data which is not deleted data + DBStatus UpdateKey(const UpdateKeyCallback &callback) override; private: DBStatus GetInner(const IOption &option, const Key &key, Value &value) const; DBStatus PutInner(const IOption &option, const Key &key, const Value &value); diff --git a/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/relational_store_delegate_impl.cpp b/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/relational_store_delegate_impl.cpp index 714364da..02a18d3d 100644 --- a/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/relational_store_delegate_impl.cpp +++ b/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/relational_store_delegate_impl.cpp @@ -160,5 +160,20 @@ DBStatus RelationalStoreDelegateImpl::RemoteQuery(const std::string &device, con } return OK; } + +DBStatus RelationalStoreDelegateImpl::RemoveDeviceData() +{ + if (conn_ == nullptr) { + LOGE("Invalid connection for operation!"); + return DB_ERROR; + } + + int errCode = conn_->RemoveDeviceData(); + if (errCode != E_OK) { + LOGW("[RelationalStore Delegate] remove device data failed:%d", errCode); + return TransferDBErrno(errCode); + } + return OK; +} } // namespace DistributedDB #endif \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/relational_store_delegate_impl.h b/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/relational_store_delegate_impl.h index 508bd945..a5a2a737 100644 --- a/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/relational_store_delegate_impl.h +++ b/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/relational_store_delegate_impl.h @@ -46,6 +46,8 @@ public: DBStatus RemoteQuery(const std::string &device, const RemoteCondition &condition, uint64_t timeout, std::shared_ptr &result) override; + DBStatus RemoveDeviceData() override; + private: static void OnSyncComplete(const std::map> &devicesStatus, const SyncStatusCallback &onComplete); diff --git a/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/relational_store_manager.cpp b/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/relational_store_manager.cpp index 84ca3ba5..c3dd979f 100644 --- a/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/relational_store_manager.cpp +++ b/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/relational_store_manager.cpp @@ -133,7 +133,7 @@ DBStatus RelationalStoreManager::CloseStore(RelationalStoreDelegate *store) std::string RelationalStoreManager::GetDistributedTableName(const std::string &device, const std::string &tableName) { - if (device.empty() || tableName.empty()) { + if ((!RuntimeContext::GetInstance()->ExistTranslateDevIdCallback() && device.empty()) || tableName.empty()) { return {}; } return DBCommon::GetDistributedTableName(device, tableName); diff --git a/kv_store/frameworks/libs/distributeddb/interfaces/src/runtime_config.cpp b/kv_store/frameworks/libs/distributeddb/interfaces/src/runtime_config.cpp index 1dbabc51..d55b996e 100644 --- a/kv_store/frameworks/libs/distributeddb/interfaces/src/runtime_config.cpp +++ b/kv_store/frameworks/libs/distributeddb/interfaces/src/runtime_config.cpp @@ -128,5 +128,10 @@ DBStatus RuntimeConfig::SetPermissionConditionCallback(const PermissionCondition int errCode = RuntimeContext::GetInstance()->SetPermissionConditionCallback(callback); return TransferDBErrno(errCode); } + +void RuntimeConfig::SetTranslateToDeviceIdCallback(const DistributedDB::TranslateToDeviceIdCallback &callback) +{ + RuntimeContext::GetInstance()->SetTranslateToDeviceIdCallback(callback); +} } // namespace DistributedDB #endif \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/storage/include/ikvdb_connection.h b/kv_store/frameworks/libs/distributeddb/storage/include/ikvdb_connection.h index 8cfebe8f..eec37ba7 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/include/ikvdb_connection.h +++ b/kv_store/frameworks/libs/distributeddb/storage/include/ikvdb_connection.h @@ -131,6 +131,8 @@ public: virtual int GetKeys(const IOption &option, const Key &keyPrefix, std::vector &keys) const = 0; virtual int GetSyncDataSize(const std::string &device, size_t &size) const = 0; + + virtual int UpdateKey(const UpdateKeyCallback &callback) = 0; }; } // namespace DistributedDB diff --git a/kv_store/frameworks/libs/distributeddb/storage/include/kvdb_manager.h b/kv_store/frameworks/libs/distributeddb/storage/include/kvdb_manager.h index 7ea47927..88f028cd 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/include/kvdb_manager.h +++ b/kv_store/frameworks/libs/distributeddb/storage/include/kvdb_manager.h @@ -128,9 +128,13 @@ private: static int TryLockDB(const KvDBProperties &kvDBProp, int retryTimes); static int UnlockDB(const KvDBProperties &kvDBProp); + static bool CheckOpenDBOptionWithCached(const KvDBProperties &properties, IKvDB *kvdb); + static std::atomic instance_; static std::mutex kvDBLock_; static std::mutex instanceLock_; + + static std::mutex fileHandleMutex_; static std::map locks_; std::map localKvDBs_; diff --git a/kv_store/frameworks/libs/distributeddb/storage/include/relational_store_connection.h b/kv_store/frameworks/libs/distributeddb/storage/include/relational_store_connection.h index 202b5f52..bd48de49 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/include/relational_store_connection.h +++ b/kv_store/frameworks/libs/distributeddb/storage/include/relational_store_connection.h @@ -53,6 +53,7 @@ public: virtual int CreateDistributedTable(const std::string &tableName) = 0; virtual int RegisterLifeCycleCallback(const DatabaseLifeCycleNotifier ¬ifier) = 0; + virtual int RemoveDeviceData() = 0; virtual int RemoveDeviceData(const std::string &device) = 0; virtual int RemoveDeviceData(const std::string &device, const std::string &tableName) = 0; virtual void RegisterObserverAction(const RelationalObserverAction &action) = 0; diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/generic_kvdb_connection.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/generic_kvdb_connection.cpp index 7e6047d1..9bd0b60c 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/generic_kvdb_connection.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/generic_kvdb_connection.cpp @@ -356,4 +356,9 @@ int GenericKvDBConnection::GetSyncDataSize(const std::string &device, size_t &si { return -E_NOT_SUPPORT; } + +int GenericKvDBConnection::UpdateKey(const UpdateKeyCallback &callback) +{ + return -E_NOT_SUPPORT; +} } \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/generic_kvdb_connection.h b/kv_store/frameworks/libs/distributeddb/storage/src/generic_kvdb_connection.h index d99aa4d6..09c1088b 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/generic_kvdb_connection.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/generic_kvdb_connection.h @@ -78,6 +78,8 @@ public: int GetKeys(const IOption &option, const Key &keyPrefix, std::vector &keys) const override; int GetSyncDataSize(const std::string &device, size_t &size) const override; + + int UpdateKey(const UpdateKeyCallback &callback) override; protected: // Get the stashed 'KvDB_ pointer' without ref. template diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/kvdb_manager.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/kvdb_manager.cpp index 162457d3..1bbba479 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/kvdb_manager.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/kvdb_manager.cpp @@ -29,6 +29,7 @@ std::atomic KvDBManager::instance_{nullptr}; std::mutex KvDBManager::kvDBLock_; std::mutex KvDBManager::instanceLock_; std::map KvDBManager::locks_; +std::mutex KvDBManager::fileHandleMutex_; namespace { DefaultFactory g_defaultFactory; @@ -120,7 +121,7 @@ int KvDBManager::ExecuteRemoveDatabase(const KvDBProperties &properties) } errCode = -E_NOT_FOUND; - for (const KvDBType kvDbType : g_dbTypeArr) { + for (KvDBType kvDbType : g_dbTypeArr) { int innerErrCode = E_OK; IKvDB *kvdb = factory->CreateKvDb(kvDbType, innerErrCode); if (innerErrCode != E_OK) { @@ -206,9 +207,12 @@ int KvDBManager::TryLockDB(const KvDBProperties &kvDBProp, int retryTimes) return E_OK; } - if (locks_.count(id) != 0) { - LOGI("db has been locked!"); - return E_OK; + { + std::lock_guard autoLock(fileHandleMutex_); + if (locks_.count(id) != 0) { + LOGI("db has been locked!"); + return E_OK; + } } std::string hexHashId = DBCommon::TransferStringToHex((id)); @@ -223,6 +227,7 @@ int KvDBManager::TryLockDB(const KvDBProperties &kvDBProp, int retryTimes) errCode = OS::FileLock(handle, false); // not block process if (errCode == E_OK) { LOGI("[%s]locked!", STR_MASK(DBCommon::TransferStringToHex(KvDBManager::GenerateKvDBIdentifier(kvDBProp)))); + std::lock_guard autoLock(fileHandleMutex_); locks_[id] = handle; return errCode; } else if (errCode == -E_BUSY) { @@ -246,23 +251,57 @@ int KvDBManager::UnlockDB(const KvDBProperties &kvDBProp) return E_OK; } std::string identifierDir = KvDBManager::GenerateKvDBIdentifier(kvDBProp); - if (locks_.count(identifierDir) == 0) { - return E_OK; + OS::FileHandle *handle = nullptr; + { + std::lock_guard autoLock(fileHandleMutex_); + if (locks_.count(identifierDir) == 0) { + return E_OK; + } + handle = locks_[identifierDir]; } - int errCode = OS::FileUnlock(locks_[identifierDir]); + int errCode = OS::FileUnlock(handle); if (errCode != E_OK) { LOGE("DB unlocked! errCode = [%d]", errCode); return errCode; } - errCode = OS::CloseFile(locks_[identifierDir]); + errCode = OS::CloseFile(handle); if (errCode != E_OK) { LOGE("DB closed! errCode = [%d]", errCode); return errCode; } + std::lock_guard autoLock(fileHandleMutex_); locks_.erase(identifierDir); return E_OK; } +bool KvDBManager::CheckOpenDBOptionWithCached(const KvDBProperties &properties, IKvDB *kvDB) +{ + bool isMemoryDb = properties.GetBoolProp(KvDBProperties::MEMORY_MODE, false); + std::string canonicalDir = properties.GetStringProp(KvDBProperties::DATA_DIR, ""); + if (!isMemoryDb && (canonicalDir.empty() || canonicalDir != kvDB->GetStorePath())) { + LOGE("Failed to check store path, the input path does not match with cached store."); + return false; + } + + bool compressOnSyncUser = properties.GetBoolProp(KvDBProperties::COMPRESS_ON_SYNC, false); + bool compressOnSyncGet = kvDB->GetMyProperties().GetBoolProp(KvDBProperties::COMPRESS_ON_SYNC, false); + if (compressOnSyncUser != compressOnSyncGet) { + LOGE("Failed to check compress option, the input %d not match with cached %d.", compressOnSyncUser, + compressOnSyncGet); + return false; + } + if (compressOnSyncUser) { + int compressRateUser = properties.GetIntProp(KvDBProperties::COMPRESSION_RATE, 0); + int compressRateGet = kvDB->GetMyProperties().GetIntProp(KvDBProperties::COMPRESSION_RATE, 0); + if (compressRateUser != compressRateGet) { + LOGE("Failed to check compress rate, the input %d not match with cached %d.", compressRateUser, + compressRateGet); + return false; + } + } + return true; +} + // Used to open a kvdb with the given property IKvDBConnection *KvDBManager::GetDatabaseConnection(const KvDBProperties &properties, int &errCode, bool isNeedIfOpened) @@ -283,10 +322,8 @@ IKvDBConnection *KvDBManager::GetDatabaseConnection(const KvDBProperties &proper LOGE("Failed to open the db:%d", errCode); } } else { - bool isMemoryDb = properties.GetBoolProp(KvDBProperties::MEMORY_MODE, false); - std::string canonicalDir = properties.GetStringProp(KvDBProperties::DATA_DIR, ""); - if (!isMemoryDb && (canonicalDir.empty() || canonicalDir != kvDB->GetStorePath())) { - LOGE("Failed to check store path, the input path does not match with cached store."); + if (!CheckOpenDBOptionWithCached(properties, kvDB)) { + LOGE("Failed to check open db option"); errCode = -E_INVALID_ARGS; } else { connection = kvDB->GetDBConnection(errCode); @@ -304,7 +341,8 @@ IKvDBConnection *KvDBManager::GetDatabaseConnection(const KvDBProperties &proper std::string userId = properties.GetStringProp(KvDBProperties::USER_ID, ""); std::string storeId = properties.GetStringProp(KvDBProperties::STORE_ID, ""); manager->DataBaseCorruptNotify(appId, userId, storeId); - LOGE("Database [%s] is corrupted:%d", STR_MASK(DBCommon::TransferStringToHex(identifier)), errCode); + LOGE("Database [%s] is corrupted or invalid passwd:%d", STR_MASK(DBCommon::TransferStringToHex(identifier)), + errCode); } return connection; @@ -447,7 +485,7 @@ int KvDBManager::CalculateKvStoreSize(const KvDBProperties &properties, uint64_t } uint64_t totalSize = 0; - for (const KvDBType kvDbType : g_dbTypeArr) { + for (KvDBType kvDbType : g_dbTypeArr) { int innerErrCode = E_OK; IKvDB *kvDB = factory->CreateKvDb(kvDbType, innerErrCode); if (innerErrCode != E_OK) { diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/relational_sync_able_storage.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/relational_sync_able_storage.cpp index 7b6be368..58fb506a 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/relational_sync_able_storage.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/relational_sync_able_storage.cpp @@ -478,8 +478,14 @@ int RelationalSyncAbleStorage::SaveSyncDataItems(const QueryObject &object, std: return errCode; } + StoreInfo info = { + storageEngine_->GetProperties().GetStringProp(DBProperties::USER_ID, ""), + storageEngine_->GetProperties().GetStringProp(DBProperties::APP_ID, ""), + storageEngine_->GetProperties().GetStringProp(DBProperties::STORE_ID, "") + }; auto inserter = RelationalSyncDataInserter::CreateInserter(deviceName, query, storageEngine_->GetSchema(), - remoteSchema.GetTable(query.GetTableName()).GetFieldInfos(), dataItems); + remoteSchema.GetTable(query.GetTableName()).GetFieldInfos(), info); + inserter.SetEntries(dataItems); auto *handle = GetHandle(true, errCode, OperatePerm::NORMAL_PERM); if (handle == nullptr) { @@ -604,12 +610,17 @@ int RelationalSyncAbleStorage::CreateDistributedDeviceTable(const std::string &d return errCode; } + StoreInfo info = { + storageEngine_->GetProperties().GetStringProp(DBProperties::USER_ID, ""), + storageEngine_->GetProperties().GetStringProp(DBProperties::APP_ID, ""), + storageEngine_->GetProperties().GetStringProp(DBProperties::STORE_ID, "") + }; for (const auto &[table, strategy] : syncStrategy) { if (!strategy.permitSync) { continue; } - errCode = handle->CreateDistributedDeviceTable(device, storageEngine_->GetSchema().GetTable(table)); + errCode = handle->CreateDistributedDeviceTable(device, storageEngine_->GetSchema().GetTable(table), info); if (errCode != E_OK) { LOGE("Create distributed device table failed. %d", errCode); break; @@ -827,7 +838,7 @@ int RelationalSyncAbleStorage::GetRemoteDeviceSchema(const std::string &deviceId LOGE("Get remote device schema from meta failed. err=%d", errCode); return errCode; } - std::string remoteSchema(remoteSchemaBuff.begin(), remoteSchemaBuff.end()); + remoteSchema = std::string(remoteSchemaBuff.begin(), remoteSchemaBuff.end()); errCode = remoteDeviceSchema_.Put(deviceId, remoteSchema); } diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/relational_sync_data_inserter.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/relational_sync_data_inserter.cpp index aeebb9fe..4ca1c35e 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/relational_sync_data_inserter.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/relational_sync_data_inserter.cpp @@ -50,11 +50,10 @@ RelationalSyncDataInserter::~RelationalSyncDataInserter() RelationalSyncDataInserter RelationalSyncDataInserter::CreateInserter(const std::string &deviceName, const QueryObject &query, const RelationalSchemaObject &localSchema, const std::vector &remoteFields, - const std::vector &entries) + const StoreInfo &info) { RelationalSyncDataInserter inserter; - inserter.SetDeviceId(deviceName); - inserter.SetEntries(entries); + inserter.SetHashDevId(DBCommon::TransferStringToHex(DBCommon::TransferHashString(deviceName))); inserter.SetRemoteFields(remoteFields); inserter.SetQuery(query); TableInfo localTable = localSchema.GetTable(query.GetTableName()); @@ -63,14 +62,14 @@ RelationalSyncDataInserter RelationalSyncDataInserter::CreateInserter(const std: if (localSchema.GetTableMode() == DistributedTableMode::COLLABORATION) { inserter.SetInsertTableName(localTable.GetTableName()); } else { - inserter.SetInsertTableName(DBCommon::GetDistributedTableName(deviceName, localTable.GetTableName())); + inserter.SetInsertTableName(DBCommon::GetDistributedTableName(deviceName, localTable.GetTableName(), info)); } return inserter; } -void RelationalSyncDataInserter::SetDeviceId(std::string deviceId) +void RelationalSyncDataInserter::SetHashDevId(const std::string &hashDevId) { - deviceId_ = std::move(deviceId); + hashDevId_ = hashDevId; } void RelationalSyncDataInserter::SetRemoteFields(std::vector remoteFields) @@ -88,7 +87,7 @@ void RelationalSyncDataInserter::SetLocalTable(TableInfo localTable) localTable_ = std::move(localTable); } -const TableInfo &RelationalSyncDataInserter::GetLocalTable() +const TableInfo &RelationalSyncDataInserter::GetLocalTable() const { return localTable_; } @@ -208,9 +207,8 @@ int RelationalSyncDataInserter::GetDeleteSyncDataStmt(sqlite3 *db, sqlite3_stmt int RelationalSyncDataInserter::GetSaveLogStatement(sqlite3 *db, sqlite3_stmt *&logStmt, sqlite3_stmt *&queryStmt) { - std::string devName = DBCommon::TransferHashString(deviceId_); const std::string tableName = DBConstant::RELATIONAL_PREFIX + query_.GetTableName() + "_log"; - std::string dataFormat = "?, '" + deviceId_ + "', ?, ?, ?, ?, ?"; + std::string dataFormat = "?, '" + hashDevId_ + "', ?, ?, ?, ?, ?"; std::string columnList = "data_key, device, ori_device, timestamp, wtimestamp, flag, hash_key"; std::string sql = "INSERT OR REPLACE INTO " + tableName + " (" + columnList + ") VALUES (" + dataFormat + ");"; @@ -251,7 +249,7 @@ int RelationalSyncDataInserter::Iterate(const std::function &s { int errCode = E_OK; for (auto &it : entries_) { - it.dev = deviceId_; + it.dev = hashDevId_; errCode = saveSyncDataItem(it); if (errCode != E_OK) { LOGE("Save sync data item failed. err=%d", errCode); diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/relational_sync_data_inserter.h b/kv_store/frameworks/libs/distributeddb/storage/src/relational_sync_data_inserter.h index 0a9bb827..714da37f 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/relational_sync_data_inserter.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/relational_sync_data_inserter.h @@ -45,15 +45,15 @@ public: static RelationalSyncDataInserter CreateInserter(const std::string &deviceName, const QueryObject &query, const RelationalSchemaObject &localSchema, const std::vector &remoteFields, - const std::vector &entries); + const StoreInfo &info); - void SetDeviceId(std::string deviceId); + void SetHashDevId(const std::string &hashDevId); // Set remote fields in cid order - void SetRemoteFields(std::vector fields); + void SetRemoteFields(std::vector remoteFields); void SetEntries(std::vector entries); void SetLocalTable(TableInfo localTable); - const TableInfo &GetLocalTable(); + const TableInfo &GetLocalTable() const; void SetQuery(QueryObject query); void SetInsertTableName(std::string tableName); @@ -73,7 +73,7 @@ private: int GetSaveLogStatement(sqlite3 *db, sqlite3_stmt *&logStmt, sqlite3_stmt *&queryStmt); - std::string deviceId_; + std::string hashDevId_; std::vector remoteFields_; std::vector entries_; TableInfo localTable_; diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_store.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_store.cpp index 59e7c790..1d85cfa0 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_store.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_store.cpp @@ -431,7 +431,7 @@ int SQLiteRelationalStore::CreateDistributedTable(const std::string &tableName) return errCode; } -int SQLiteRelationalStore::RemoveDeviceData(const std::string &device, const std::string &tableName) +int SQLiteRelationalStore::RemoveDeviceData() { auto mode = static_cast(sqliteStorageEngine_->GetProperties().GetIntProp( RelationalDBProperties::DISTRIBUTED_TABLE_MODE, DistributedTableMode::SPLIT_BY_DEVICE)); @@ -441,49 +441,83 @@ int SQLiteRelationalStore::RemoveDeviceData(const std::string &device, const std } TableInfoMap tables = sqliteStorageEngine_->GetSchema().GetTables(); // TableInfoMap - if (!tableName.empty() && tables.find(tableName) == tables.end()) { - LOGW("Remove device data with table name which is not a distributed table or not exist."); + if (tables.empty()) { return E_OK; } int errCode = E_OK; - auto *handle = GetHandle(true, errCode); + auto *handle = GetHandleAndStartTransaction(errCode); if (handle == nullptr) { return errCode; } - errCode = handle->StartTransaction(TransactType::IMMEDIATE); - if (errCode != E_OK) { - ReleaseHandle(handle); - return errCode; - } - - errCode = handle->DeleteDistributedDeviceTable(device, tableName); - if (errCode != E_OK) { - LOGE("delete device data failed. %d", errCode); - goto END; - } + std::vector tableNameList; + for (const auto &table: tables) { + errCode = handle->DeleteDistributedDeviceTable("", table.second.GetTableName()); + if (errCode != E_OK) { + LOGE("delete device data failed. %d", errCode); + break; + } - for (const auto &it : tables) { - if (tableName.empty() || it.second.GetTableName() == tableName) { - errCode = handle->DeleteDistributedDeviceTableLog(device, it.second.GetTableName()); - if (errCode != E_OK) { - LOGE("delete device data failed. %d", errCode); - break; - } + errCode = handle->DeleteDistributedAllDeviceTableLog(table.second.GetTableName()); + if (errCode != E_OK) { + LOGE("delete device data failed. %d", errCode); + break; } + tableNameList.push_back(table.second.GetTableName()); } -END: if (errCode != E_OK) { (void)handle->Rollback(); ReleaseHandle(handle); return errCode; } + errCode = handle->Commit(); ReleaseHandle(handle); storageEngine_->NotifySchemaChanged(); - return (errCode != E_OK) ? errCode : syncAbleEngine_->EraseDeviceWaterMark(device, true, tableName); + return (errCode != E_OK) ? errCode : EraseAllDeviceWatermark(tableNameList); +} + +int SQLiteRelationalStore::RemoveDeviceData(const std::string &device, const std::string &tableName) +{ + auto mode = static_cast(sqliteStorageEngine_->GetProperties().GetIntProp( + RelationalDBProperties::DISTRIBUTED_TABLE_MODE, DistributedTableMode::SPLIT_BY_DEVICE)); + if (mode == DistributedTableMode::COLLABORATION) { + LOGE("Not support remove device data in collaboration mode."); + return -E_NOT_SUPPORT; + } + + TableInfoMap tables = sqliteStorageEngine_->GetSchema().GetTables(); // TableInfoMap + if (tables.empty() || (!tableName.empty() && tables.find(tableName) == tables.end())) { + LOGE("Remove device data with table name which is not a distributed table or no distributed table found."); + return -E_DISTRIBUTED_SCHEMA_NOT_FOUND; + } + + bool isNeedHash = false; + std::string hashDeviceId; + int errCode = syncAbleEngine_->GetHashDeviceId(device, hashDeviceId); + if (errCode == -E_NOT_SUPPORT) { + isNeedHash = true; + hashDeviceId = device; + errCode = E_OK; + } + if (errCode != E_OK) { + return errCode; + } + if (isNeedHash) { + // check device is uuid in meta + std::set hashDevices; + errCode = GetExistDevices(hashDevices); + if (errCode != E_OK) { + return errCode; + } + if (hashDevices.find(DBCommon::TransferHashString(device)) == hashDevices.end()) { + LOGD("[SQLiteRelationalStore] not match device, just return"); + return E_OK; + } + } + return RemoveDeviceDataInner(hashDeviceId, device, tableName, isNeedHash); } void SQLiteRelationalStore::RegisterObserverAction(const RelationalObserverAction &action) @@ -673,5 +707,126 @@ int SQLiteRelationalStore::RemoteQuery(const std::string &device, const RemoteCo return syncAbleEngine_->RemoteQuery(device, condition, timeout, connectionId, result); } + +int SQLiteRelationalStore::EraseAllDeviceWatermark(const std::vector &tableNameList) +{ + std::set devices; + int errCode = GetExistDevices(devices); + if (errCode != E_OK) { + return errCode; + } + for (const auto &tableName: tableNameList) { + for (const auto &device: devices) { + errCode = syncAbleEngine_->EraseDeviceWaterMark(device, false, tableName); + if (errCode != E_OK) { + return errCode; + } + } + } + return errCode; +} + +std::string SQLiteRelationalStore::GetDevTableName(const std::string &device, const std::string &hashDev) const +{ + std::string devTableName; + StoreInfo info = { + sqliteStorageEngine_->GetProperties().GetStringProp(DBProperties::USER_ID, ""), + sqliteStorageEngine_->GetProperties().GetStringProp(DBProperties::APP_ID, ""), + sqliteStorageEngine_->GetProperties().GetStringProp(DBProperties::STORE_ID, "") + }; + if (RuntimeContext::GetInstance()->TranslateDeviceId(device, info, devTableName) != E_OK) { + devTableName = hashDev; + } + return devTableName; +} + +SQLiteSingleVerRelationalStorageExecutor *SQLiteRelationalStore::GetHandleAndStartTransaction(int &errCode) const +{ + auto *handle = GetHandle(true, errCode); + if (handle == nullptr) { + return nullptr; + } + + errCode = handle->StartTransaction(TransactType::IMMEDIATE); + if (errCode != E_OK) { + ReleaseHandle(handle); + return nullptr; + } + return handle; +} + +int SQLiteRelationalStore::RemoveDeviceDataInner(const std::string &mappingDev, const std::string &device, + const std::string &tableName, bool isNeedHash) +{ + int errCode = E_OK; + auto *handle = GetHandle(true, errCode); + if (handle == nullptr) { + return errCode; + } + + errCode = handle->StartTransaction(TransactType::IMMEDIATE); + if (errCode != E_OK) { + ReleaseHandle(handle); + return errCode; + } + + std::string hashHexDev; + std::string hashDev; + std::string devTableName; + if (!isNeedHash) { + // if is not need hash mappingDev mean hash(uuid) device is param device + hashHexDev = DBCommon::TransferStringToHex(mappingDev); + hashDev = mappingDev; + devTableName = device; + } else { + // if is need hash mappingDev mean uuid + hashDev = DBCommon::TransferHashString(mappingDev); + hashHexDev = DBCommon::TransferStringToHex(hashDev); + devTableName = GetDevTableName(mappingDev, hashHexDev); + } + errCode = handle->DeleteDistributedDeviceTable(devTableName, tableName); + TableInfoMap tables = sqliteStorageEngine_->GetSchema().GetTables(); // TableInfoMap + if (errCode != E_OK) { + LOGE("delete device data failed. %d", errCode); + goto END; + } + + for (const auto &it : tables) { + if (tableName.empty() || it.second.GetTableName() == tableName) { + errCode = handle->DeleteDistributedDeviceTableLog(hashHexDev, it.second.GetTableName()); + if (errCode != E_OK) { + LOGE("delete device data failed. %d", errCode); + break; + } + } + } + +END: + if (errCode != E_OK) { + (void)handle->Rollback(); + ReleaseHandle(handle); + return errCode; + } + errCode = handle->Commit(); + ReleaseHandle(handle); + storageEngine_->NotifySchemaChanged(); + return (errCode != E_OK) ? errCode : syncAbleEngine_->EraseDeviceWaterMark(hashDev, false, tableName); +} + +int SQLiteRelationalStore::GetExistDevices(std::set &hashDevices) +{ + int errCode = E_OK; + auto *handle = GetHandle(true, errCode); + if (handle == nullptr) { + LOGE("[SingleVerRDBStore] GetExistsDeviceList get handle failed:%d", errCode); + return errCode; + } + errCode = handle->GetExistsDeviceList(hashDevices); + if (errCode != E_OK) { + LOGE("[SingleVerRDBStore] Get remove device list from meta failed. err=%d", errCode); + } + ReleaseHandle(handle); + return errCode; +} } #endif \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_store.h b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_store.h index 216b0ad2..7603a830 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_store.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_store.h @@ -58,6 +58,7 @@ public: int CreateDistributedTable(const std::string &tableName); + int RemoveDeviceData(); int RemoveDeviceData(const std::string &device, const std::string &tableName); void RegisterObserverAction(const RelationalObserverAction &action); @@ -98,6 +99,17 @@ private: void IncreaseConnectionCounter(); int InitStorageEngine(const RelationalDBProperties &kvDBProp); + int EraseAllDeviceWatermark(const std::vector &tableNameList); + + std::string GetDevTableName(const std::string &device, const std::string &hashDev) const; + + SQLiteSingleVerRelationalStorageExecutor *GetHandleAndStartTransaction(int &errCode) const; + + int RemoveDeviceDataInner(const std::string &mappingDev, const std::string &device, + const std::string &tableName, bool isNeedHash); + + int GetExistDevices(std::set &hashDevices); + // use for sync Interactive std::unique_ptr syncAbleEngine_ = nullptr; // For storage operate sync function // use ref obj same as kv diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_store_connection.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_store_connection.cpp index 86e72eed..57fb3c36 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_store_connection.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_store_connection.cpp @@ -156,6 +156,21 @@ int SQLiteRelationalStoreConnection::CreateDistributedTable(const std::string &t return errCode; } +int SQLiteRelationalStoreConnection::RemoveDeviceData() +{ + auto *store = GetDB(); + if (store == nullptr) { + LOGE("[RelationalConnection] store is null, get DB failed!"); + return -E_INVALID_CONNECTION; + } + + int errCode = store->RemoveDeviceData(); + if (errCode != E_OK) { + LOGE("[RelationalConnection] remove device data failed. %d", errCode); + } + return errCode; +} + int SQLiteRelationalStoreConnection::RemoveDeviceData(const std::string &device) { return RemoveDeviceData(device, {}); diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_store_connection.h b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_store_connection.h index 3c51d21d..0c85ca89 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_store_connection.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_store_connection.h @@ -39,6 +39,7 @@ public: int CreateDistributedTable(const std::string &tableName) override; int RegisterLifeCycleCallback(const DatabaseLifeCycleNotifier ¬ifier) override; + int RemoveDeviceData() override; int RemoveDeviceData(const std::string &device) override; int RemoveDeviceData(const std::string &device, const std::string &tableName) override; void RegisterObserverAction(const RelationalObserverAction &action) override; diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_meta_executor.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_meta_executor.cpp new file mode 100644 index 00000000..fdc929b8 --- /dev/null +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_meta_executor.cpp @@ -0,0 +1,113 @@ +/* + * 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. + */ + +#include "sqlite_meta_executor.h" + +#include "db_common.h" +#include "db_constant.h" +namespace DistributedDB { +int SqliteMetaExecutor::GetMetaKeysByKeyPrefix(const std::string &keyPre, sqlite3 *dbHandle, MetaMode metaMode, + bool isMemDb, std::set &outKeys) +{ + sqlite3_stmt *statement = nullptr; + std::string sqlStr; + switch (metaMode) { + case MetaMode::KV: + sqlStr = SELECT_META_KEYS_BY_PREFIX; + break; + case MetaMode::KV_ATTACH: + sqlStr = SELECT_ATTACH_META_KEYS_BY_PREFIX; + break; + case MetaMode::RDB: + sqlStr = SELECT_RDB_META_KEYS_BY_PREFIX; + break; + default: + return -E_INVALID_ARGS; + } + int errCode = SQLiteUtils::GetStatement(dbHandle, sqlStr, statement); + if (errCode != E_OK) { + LOGE("[SqliteMetaExecutor] Get statement failed:%d", errCode); + return errCode; + } + + Key keyPrefix; + DBCommon::StringToVector(keyPre + '%', keyPrefix); + errCode = SQLiteUtils::BindBlobToStatement(statement, 1, keyPrefix); // 1: bind index for prefix key + if (errCode != E_OK) { + LOGE("[SqliteMetaExecutor] Bind statement failed:%d", errCode); + SQLiteUtils::ResetStatement(statement, true, errCode); + return errCode; + } + + std::vector keys; + errCode = GetAllKeys(statement, isMemDb, keys); + SQLiteUtils::ResetStatement(statement, true, errCode); + for (const auto &it : keys) { + if (it.size() >= keyPre.size() + DBConstant::HASH_KEY_SIZE) { + outKeys.insert({it.begin() + keyPre.size(), it.begin() + keyPre.size() + DBConstant::HASH_KEY_SIZE}); + } else { + LOGW("[SqliteMetaExecutor] Get invalid key, size=%zu", it.size()); + } + } + return errCode; +} + +int SqliteMetaExecutor::GetAllKeys(sqlite3_stmt *statement, bool isMemDb, std::vector &keys) +{ + if (statement == nullptr) { + return -E_INVALID_DB; + } + int errCode; + do { + errCode = SQLiteUtils::StepWithRetry(statement, isMemDb); + if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { + Key key; + errCode = SQLiteUtils::GetColumnBlobValue(statement, 0, key); + if (errCode != E_OK) { + break; + } + + keys.push_back(std::move(key)); + } else if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { + errCode = E_OK; + break; + } else { + LOGE("SQLite step for getting all keys failed:%d", errCode); + break; + } + } while (true); + return errCode; +} + +int SqliteMetaExecutor::GetExistsDevicesFromMeta(sqlite3 *dbHandle, MetaMode metaMode, + bool isMemDb, std::set &devices) +{ + int errCode = GetMetaKeysByKeyPrefix(DBConstant::DEVICEID_PREFIX_KEY, dbHandle, metaMode, isMemDb, devices); + if (errCode != E_OK) { + LOGE("Get meta data key failed. err=%d", errCode); + return errCode; + } + errCode = GetMetaKeysByKeyPrefix(DBConstant::QUERY_SYNC_PREFIX_KEY, dbHandle, metaMode, isMemDb, devices); + if (errCode != E_OK) { + LOGE("Get meta data key failed. err=%d", errCode); + return errCode; + } + errCode = GetMetaKeysByKeyPrefix(DBConstant::DELETE_SYNC_PREFIX_KEY, dbHandle, metaMode, isMemDb, devices); + if (errCode != E_OK) { + LOGE("Get meta data key failed. err=%d", errCode); + } + return errCode; +} +} \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_meta_executor.h b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_meta_executor.h new file mode 100644 index 00000000..f2890e7b --- /dev/null +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_meta_executor.h @@ -0,0 +1,47 @@ +/* + * 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 SQLITE_META_EXECUTOR_H +#define SQLITE_META_EXECUTOR_H + +#include "sqlite_utils.h" + +namespace DistributedDB { +class SqliteMetaExecutor { +public: + enum class MetaMode { + KV = 0, + KV_ATTACH = 1, + RDB = 2 + }; + static int GetMetaKeysByKeyPrefix(const std::string &keyPre, sqlite3 *dbHandle, MetaMode metaMode, bool isMemDb, + std::set &outKeys); + + static int GetAllKeys(sqlite3_stmt *statement, bool isMemDb, std::vector &keys); + + static int GetExistsDevicesFromMeta(sqlite3 *dbHandle, MetaMode metaMode, + bool isMemDb, std::set &devices); +private: + static constexpr const char *SELECT_ATTACH_META_KEYS_BY_PREFIX = + "SELECT key FROM meta.meta_data where key like ?;"; + + static constexpr const char *SELECT_META_KEYS_BY_PREFIX = + "SELECT key FROM meta_data where key like ?;"; + + static constexpr const char *SELECT_RDB_META_KEYS_BY_PREFIX = + "SELECT key FROM naturalbase_rdb_aux_metadata where key like ?;"; +}; +} // DistributedDB +#endif // SQLITE_META_EXECUTOR_H diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_query_helper.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_query_helper.cpp index ae76af04..9ad4757a 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_query_helper.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_query_helper.cpp @@ -829,8 +829,19 @@ int SqliteQueryHelper::GetSubscribeCondition(const std::string &accessStr, std:: conditionStr += " (1 = 1) "; return E_OK; } - // json_extract_by_path function will return error when value is empty, check it before - conditionStr += "((length(" + accessStr + "value) != 0 AND " + accessStr + "value IS NOT NULL) AND "; + + bool hasQueryByValue = std::any_of(queryObjNodes_.begin(), queryObjNodes_.end(), [](const QueryObjNode &it) { + return GetSymbolType(it.operFlag) == SymbolType::COMPARE_SYMBOL || + GetSymbolType(it.operFlag) == SymbolType::RELATIONAL_SYMBOL || + GetSymbolType(it.operFlag) == SymbolType::RANGE_SYMBOL; + }); + if (hasQueryByValue) { + // json_extract_by_path function will return error when value is empty, check it before when query by value + conditionStr += "((length(" + accessStr + "value) != 0 AND " + accessStr + "value IS NOT NULL) AND "; + } else { + conditionStr += "("; + } + if (hasPrefixKey_) { conditionStr += "(hex(" + accessStr + "key) LIKE '" + DBCommon::VectorToHexString(prefixKey_) + "%')"; } diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_natural_store.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_natural_store.cpp index 62b1a518..b1240bdf 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_natural_store.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_natural_store.cpp @@ -413,13 +413,13 @@ int SQLiteSingleVerNaturalStore::GetAndInitStorageEngine(const KvDBProperties &k } if (storageEngine_->IsEngineCorrupted()) { - LOGE("[SqlSinStore][GetAndInitStorageEngine] database engine is corrupted, not need continue to open!"); + LOGE("[SqlSinStore][GetAndInitStorageEngine] database engine is corrupted or invalid passwd, stop open!"); return -E_INVALID_PASSWD_OR_CORRUPTED_DB; } errCode = InitDatabaseContext(kvDBProp); if (errCode != E_OK) { - LOGE("[SqlSinStore][Open] Init database context fail! errCode = [%d]", errCode); + LOGE("[SqlSinStore][GetAndInitStorageEngine] Init database context fail! errCode = [%d]", errCode); } return errCode; } @@ -974,55 +974,28 @@ int SQLiteSingleVerNaturalStore::RemoveDeviceData(const std::string &deviceName, if (!isInSync && !CheckWritePermission()) { return -E_NOT_PERMIT; } - int errCode = E_OK; - SQLiteSingleVerStorageExecutor *handle = GetHandle(true, errCode); - if (handle == nullptr) { - LOGE("[SingleVerNStore] RemoveDeviceData get handle failed:%d", errCode); - return errCode; - } - uint64_t logFileSize = handle->GetLogFileSize(); - ReleaseHandle(handle); - if (logFileSize > GetMaxLogSize()) { - LOGW("[SingleVerNStore] RmDevData log size[%" PRIu64 "] over the limit", logFileSize); - return -E_LOG_OVER_LIMITS; - } - - bool isNeedHash = true; - std::set removeDevices; - if (deviceName.empty()) { - errCode = GetExistsDeviceList(removeDevices); - if (errCode != E_OK) { - LOGE("[SingleVerNStore] get remove device list failed:%d", errCode); - return errCode; - } - isNeedHash = false; - } else { - removeDevices.insert(deviceName); - } - - LOGD("[SingleVerNStore] remove device data, size=%zu", removeDevices.size()); - for (const auto &iterDevice : removeDevices) { - // Call the syncer module to erase the water mark. - errCode = EraseDeviceWaterMark(iterDevice, isNeedHash); - if (errCode != E_OK) { - LOGE("[SingleVerNStore] erase water mark failed:%d", errCode); - return errCode; + std::string hashDeviceId; + bool hash = false; + do { + if (!deviceName.empty() && !isInSync) { + int errCode = GetHashDeviceId(deviceName, hashDeviceId); + if (errCode == -E_NOT_SUPPORT) { + break; + } + if (errCode != E_OK) { + return errCode; + } + hash = true; } + } while (false); + if (!hash) { + hashDeviceId = DBCommon::TransferHashString(deviceName); } - if (IsExtendedCacheDBMode()) { - errCode = RemoveDeviceDataInCacheMode(deviceName, isNeedNotify); - } else { - errCode = RemoveDeviceDataNormally(deviceName, isNeedNotify); - } - if (errCode != E_OK) { - LOGE("[SingleVerNStore] RemoveDeviceData failed:%d", errCode); - } - - return errCode; + return RemoveDeviceDataInner(hashDeviceId, isNeedNotify, isInSync); } -int SQLiteSingleVerNaturalStore::RemoveDeviceDataInCacheMode(const std::string &deviceName, bool isNeedNotify) +int SQLiteSingleVerNaturalStore::RemoveDeviceDataInCacheMode(const std::string &hashDev, bool isNeedNotify) { int errCode = E_OK; SQLiteSingleVerStorageExecutor *handle = GetHandle(true, errCode); @@ -1032,7 +1005,7 @@ int SQLiteSingleVerNaturalStore::RemoveDeviceDataInCacheMode(const std::string & } uint64_t recordVersion = GetAndIncreaseCacheRecordVersion(); LOGI("Remove device data in cache mode isNeedNotify:%d, recordVersion:%" PRIu64, isNeedNotify, recordVersion); - errCode = handle->RemoveDeviceDataInCacheMode(deviceName, isNeedNotify, recordVersion); + errCode = handle->RemoveDeviceDataInCacheMode(hashDev, isNeedNotify, recordVersion); if (errCode != E_OK) { LOGE("[SingleVerNStore] RemoveDeviceDataInCacheMode failed:%d", errCode); } @@ -1040,7 +1013,7 @@ int SQLiteSingleVerNaturalStore::RemoveDeviceDataInCacheMode(const std::string & return errCode; } -int SQLiteSingleVerNaturalStore::RemoveDeviceDataNormally(const std::string &deviceName, bool isNeedNotify) +int SQLiteSingleVerNaturalStore::RemoveDeviceDataNormally(const std::string &hashDev, bool isNeedNotify) { int errCode = E_OK; SQLiteSingleVerStorageExecutor *handle = GetHandle(true, errCode); @@ -1051,11 +1024,11 @@ int SQLiteSingleVerNaturalStore::RemoveDeviceDataNormally(const std::string &dev std::vector entries; if (isNeedNotify) { - handle->GetAllSyncedEntries(deviceName, entries); + handle->GetAllSyncedEntries(hashDev, entries); } LOGI("Remove device data:%d", isNeedNotify); - errCode = handle->RemoveDeviceData(deviceName); + errCode = handle->RemoveDeviceData(hashDev); ReleaseHandle(handle); if (errCode == E_OK && isNeedNotify) { NotifyRemovedData(entries); @@ -1120,7 +1093,7 @@ SQLiteSingleVerStorageExecutor *SQLiteSingleVerNaturalStore::GetHandle(bool isWr CorruptNotify(); errCode = -E_INVALID_PASSWD_OR_CORRUPTED_DB; engineMutex_.unlock_shared(); // unlock when get handle failed. - LOGI("Handle is corrupted can not to get! errCode = [%d]", errCode); + LOGI("Handle is corrupted or invalid passwd, can not to get! errCode = [%d]", errCode); return nullptr; } @@ -2410,5 +2383,52 @@ void SQLiteSingleVerNaturalStore::Dump(int fd) SyncAbleKvDB::Dump(fd); } +int SQLiteSingleVerNaturalStore::RemoveDeviceDataInner(const std::string &hashDev, bool isNeedNotify, bool isInSync) +{ + int errCode = E_OK; + SQLiteSingleVerStorageExecutor *handle = GetHandle(true, errCode); + if (handle == nullptr) { + LOGE("[SingleVerNStore] RemoveDeviceData get handle failed:%d", errCode); + return errCode; + } + uint64_t logFileSize = handle->GetLogFileSize(); + ReleaseHandle(handle); + if (logFileSize > GetMaxLogSize()) { + LOGW("[SingleVerNStore] RmDevData log size[%" PRIu64 "] over the limit", logFileSize); + return -E_LOG_OVER_LIMITS; + } + + std::set removeDevices; + if (hashDev.empty()) { + errCode = GetExistsDeviceList(removeDevices); + if (errCode != E_OK) { + LOGE("[SingleVerNStore] get remove device list failed:%d", errCode); + return errCode; + } + } else { + removeDevices.insert(hashDev); + } + + LOGD("[SingleVerNStore] remove device data, size=%zu", removeDevices.size()); + for (const auto &iterDevice : removeDevices) { + // Call the syncer module to erase the water mark. + errCode = EraseDeviceWaterMark(iterDevice, false); + if (errCode != E_OK) { + LOGE("[SingleVerNStore] erase water mark failed:%d", errCode); + return errCode; + } + } + + if (IsExtendedCacheDBMode()) { + errCode = RemoveDeviceDataInCacheMode(hashDev, isNeedNotify); + } else { + errCode = RemoveDeviceDataNormally(hashDev, isNeedNotify); + } + if (errCode != E_OK) { + LOGE("[SingleVerNStore] RemoveDeviceData failed:%d", errCode); + } + + return errCode; +} DEFINE_OBJECT_TAG_FACILITIES(SQLiteSingleVerNaturalStore) } diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_natural_store.h b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_natural_store.h index d9a63145..4ef2d756 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_natural_store.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_natural_store.h @@ -244,9 +244,9 @@ private: // Change value that should be amended, and neglect value that is incompatible void CheckAmendValueContentForSyncProcedure(std::vector &dataItems) const; - int RemoveDeviceDataInCacheMode(const std::string &deviceName, bool isNeedNotify); + int RemoveDeviceDataInCacheMode(const std::string &hashDev, bool isNeedNotify); - int RemoveDeviceDataNormally(const std::string &deviceName, bool isNeedNotify); + int RemoveDeviceDataNormally(const std::string &hashDev, bool isNeedNotify); int SaveSyncDataToMain(const QueryObject &query, std::vector &dataItems, const DeviceInfo &deviceInfo); @@ -275,6 +275,8 @@ private: int GetExistsDeviceList(std::set &devices) const; + int RemoveDeviceDataInner(const std::string &hashDev, bool isNeedNotify, bool isInSync); + DECLARE_OBJECT_TAG(SQLiteSingleVerNaturalStore); Timestamp currentMaxTimestamp_ = 0; diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_natural_store_connection.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_natural_store_connection.cpp index ca6de67d..45072d6b 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_natural_store_connection.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_natural_store_connection.cpp @@ -1833,5 +1833,31 @@ int SQLiteSingleVerNaturalStoreConnection::GetEntriesInner(bool isGetValue, cons return errCode; } +int SQLiteSingleVerNaturalStoreConnection::UpdateKey(const DistributedDB::UpdateKeyCallback &callback) +{ + if (IsExtendedCacheDBMode()) { + LOGE("[Connection] Not support update key in cache mode"); + return -E_NOT_SUPPORT; + } + int errCode = E_OK; + { + std::lock_guard lock(transactionMutex_); + if (writeHandle_ != nullptr) { + LOGD("[Connection] Transaction started already."); + errCode = writeHandle_->UpdateKey(callback); + return errCode; + } + } + + SQLiteSingleVerStorageExecutor *handle = GetExecutor(true, errCode); + if (handle == nullptr) { + LOGE("[Connection]::[UpdateKey] Get executor failed, errCode = [%d]", errCode); + return errCode; + } + + errCode = handle->UpdateKey(callback); + ReleaseExecutor(handle); + return errCode; +} DEFINE_OBJECT_TAG_FACILITIES(SQLiteSingleVerNaturalStoreConnection) } \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_natural_store_connection.h b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_natural_store_connection.h index 84381bfc..330876c6 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_natural_store_connection.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_natural_store_connection.h @@ -107,6 +107,7 @@ public: int GetKeys(const IOption &option, const Key &keyPrefix, std::vector &keys) const override; + int UpdateKey(const UpdateKeyCallback &callback) override; private: int CheckMonoStatus(OperatePerm perm); diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_relational_storage_executor.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_relational_storage_executor.cpp index 02c5c7a6..68aab389 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_relational_storage_executor.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_relational_storage_executor.cpp @@ -23,6 +23,7 @@ #include "log_table_manager_factory.h" #include "relational_row_data_impl.h" #include "res_finalizer.h" +#include "sqlite_meta_executor.h" #include "sqlite_relational_utils.h" namespace DistributedDB { @@ -210,8 +211,7 @@ int GetDeviceTableName(sqlite3 *handle, const std::string &tableName, const std: if (device.empty() && tableName.empty()) { // device and table name should not both be empty return -E_INVALID_ARGS; } - std::string deviceHash = DBCommon::TransferStringToHex(DBCommon::TransferHashString(device)); - std::string devicePattern = device.empty() ? "%" : deviceHash; + std::string devicePattern = device.empty() ? "%" : device; std::string tablePattern = tableName.empty() ? "%" : tableName; std::string deviceTableName = DBConstant::RELATIONAL_PREFIX + tablePattern + "_" + devicePattern; @@ -579,33 +579,6 @@ int SQLiteSingleVerRelationalStorageExecutor::DeleteMetaDataByPrefixKey(const Ke return CheckCorruptedStatus(errCode); } -static int GetAllKeys(sqlite3_stmt *statement, std::vector &keys) -{ - if (statement == nullptr) { - return -E_INVALID_DB; - } - int errCode; - do { - errCode = SQLiteUtils::StepWithRetry(statement, false); - if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { - Key key; - errCode = SQLiteUtils::GetColumnBlobValue(statement, 0, key); - if (errCode != E_OK) { - break; - } - - keys.push_back(std::move(key)); - } else if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { - errCode = E_OK; - break; - } else { - LOGE("SQLite step for getting all keys failed:%d", errCode); - break; - } - } while (true); - return errCode; -} - int SQLiteSingleVerRelationalStorageExecutor::GetAllMetaKeys(std::vector &keys) const { static const std::string SELECT_ALL_META_KEYS = "SELECT key FROM " + DBConstant::RELATIONAL_PREFIX + "metadata;"; @@ -615,7 +588,7 @@ int SQLiteSingleVerRelationalStorageExecutor::GetAllMetaKeys(std::vector &k LOGE("[Relational][GetAllKey] Get statement failed:%d", errCode); return errCode; } - errCode = GetAllKeys(statement, keys); + errCode = SqliteMetaExecutor::GetAllKeys(statement, isMemDb_, keys); SQLiteUtils::ResetStatement(statement, true, errCode); return errCode; } @@ -683,33 +656,33 @@ int SQLiteSingleVerRelationalStorageExecutor::SaveSyncLog(sqlite3_stmt *statemen } int SQLiteSingleVerRelationalStorageExecutor::DeleteSyncDataItem(const DataItem &dataItem, - RelationalSyncDataInserter &inserter, sqlite3_stmt *&stmt) + RelationalSyncDataInserter &inserter, sqlite3_stmt *&rmDataStmt) { - if (stmt == nullptr) { - int errCode = inserter.GetDeleteSyncDataStmt(dbHandle_, stmt); + if (rmDataStmt == nullptr) { + int errCode = inserter.GetDeleteSyncDataStmt(dbHandle_, rmDataStmt); if (errCode != E_OK) { LOGE("[DeleteSyncDataItem] Get statement fail!, errCode:%d", errCode); return errCode; } } - int errCode = SQLiteUtils::BindBlobToStatement(stmt, 1, dataItem.hashKey); // 1 means hash_key index + int errCode = SQLiteUtils::BindBlobToStatement(rmDataStmt, 1, dataItem.hashKey); // 1 means hash_key index if (errCode != E_OK) { - SQLiteUtils::ResetStatement(stmt, true, errCode); + SQLiteUtils::ResetStatement(rmDataStmt, true, errCode); return errCode; } if (mode_ != DistributedTableMode::COLLABORATION) { - errCode = SQLiteUtils::BindTextToStatement(stmt, 2, dataItem.dev); // 2 means device index + errCode = SQLiteUtils::BindTextToStatement(rmDataStmt, 2, dataItem.dev); // 2 means device index if (errCode != E_OK) { - SQLiteUtils::ResetStatement(stmt, true, errCode); + SQLiteUtils::ResetStatement(rmDataStmt, true, errCode); return errCode; } } - errCode = SQLiteUtils::StepWithRetry(stmt, isMemDb_); + errCode = SQLiteUtils::StepWithRetry(rmDataStmt, isMemDb_); if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { errCode = E_OK; } - SQLiteUtils::ResetStatement(stmt, false, errCode); // Finalize outside. + SQLiteUtils::ResetStatement(rmDataStmt, false, errCode); // Finalize outside. return errCode; } @@ -745,33 +718,33 @@ int SQLiteSingleVerRelationalStorageExecutor::SaveSyncDataItem(const DataItem &d } int SQLiteSingleVerRelationalStorageExecutor::DeleteSyncLog(const DataItem &dataItem, - RelationalSyncDataInserter &inserter, sqlite3_stmt *&stmt) + RelationalSyncDataInserter &inserter, sqlite3_stmt *&rmLogStmt) { - if (stmt == nullptr) { - int errCode = inserter.GetDeleteLogStmt(dbHandle_, stmt); + if (rmLogStmt == nullptr) { + int errCode = inserter.GetDeleteLogStmt(dbHandle_, rmLogStmt); if (errCode != E_OK) { LOGE("[DeleteSyncLog] Get statement fail!"); return errCode; } } - int errCode = SQLiteUtils::BindBlobToStatement(stmt, 1, dataItem.hashKey); // 1 means hashkey index + int errCode = SQLiteUtils::BindBlobToStatement(rmLogStmt, 1, dataItem.hashKey); // 1 means hashkey index if (errCode != E_OK) { - SQLiteUtils::ResetStatement(stmt, true, errCode); + SQLiteUtils::ResetStatement(rmLogStmt, true, errCode); return errCode; } if (mode_ != DistributedTableMode::COLLABORATION) { - errCode = SQLiteUtils::BindTextToStatement(stmt, 2, dataItem.dev); // 2 means device index + errCode = SQLiteUtils::BindTextToStatement(rmLogStmt, 2, dataItem.dev); // 2 means device index if (errCode != E_OK) { - SQLiteUtils::ResetStatement(stmt, true, errCode); + SQLiteUtils::ResetStatement(rmLogStmt, true, errCode); return errCode; } } - errCode = SQLiteUtils::StepWithRetry(stmt, isMemDb_); + errCode = SQLiteUtils::StepWithRetry(rmLogStmt, isMemDb_); if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { errCode = E_OK; } - SQLiteUtils::ResetStatement(stmt, false, errCode); // Finalize outside. + SQLiteUtils::ResetStatement(rmLogStmt, false, errCode); // Finalize outside. return errCode; } @@ -1091,6 +1064,12 @@ int SQLiteSingleVerRelationalStorageExecutor::DeleteDistributedDeviceTable(const return errCode; } +int SQLiteSingleVerRelationalStorageExecutor::DeleteDistributedAllDeviceTableLog(const std::string &tableName) +{ + std::string deleteLogSql = "DELETE FROM " + DBConstant::RELATIONAL_PREFIX + tableName + "_log WHERE flag&0x02=0"; + return SQLiteUtils::ExecuteRawSQL(dbHandle_, deleteLogSql); +} + int SQLiteSingleVerRelationalStorageExecutor::DeleteDistributedDeviceTableLog(const std::string &device, const std::string &tableName) { @@ -1179,7 +1158,7 @@ int SQLiteSingleVerRelationalStorageExecutor::CheckAndCleanDistributedTable(cons } int SQLiteSingleVerRelationalStorageExecutor::CreateDistributedDeviceTable(const std::string &device, - const TableInfo &baseTbl) + const TableInfo &baseTbl, const StoreInfo &info) { if (dbHandle_ == nullptr) { return -E_INVALID_DB; @@ -1189,7 +1168,7 @@ int SQLiteSingleVerRelationalStorageExecutor::CreateDistributedDeviceTable(const return -E_INVALID_ARGS; } - std::string deviceTableName = DBCommon::GetDistributedTableName(device, baseTbl.GetTableName()); + std::string deviceTableName = DBCommon::GetDistributedTableName(device, baseTbl.GetTableName(), info); int errCode = SQLiteUtils::CreateSameStuTable(dbHandle_, baseTbl, deviceTableName); if (errCode != E_OK) { LOGE("Create device table failed. %d", errCode); @@ -1370,5 +1349,11 @@ int SQLiteSingleVerRelationalStorageExecutor::CheckEncryptedOrCorrupted() const } return errCode; } + +int SQLiteSingleVerRelationalStorageExecutor::GetExistsDeviceList(std::set &devices) const +{ + return SqliteMetaExecutor::GetExistsDevicesFromMeta(dbHandle_, SqliteMetaExecutor::MetaMode::RDB, + isMemDb_, devices); +} } // namespace DistributedDB #endif diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_relational_storage_executor.h b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_relational_storage_executor.h index ecbda664..b90d2a8c 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_relational_storage_executor.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_relational_storage_executor.h @@ -64,6 +64,8 @@ public: int DeleteDistributedDeviceTable(const std::string &device, const std::string &tableName); + int DeleteDistributedAllDeviceTableLog(const std::string &tableName); + int DeleteDistributedDeviceTableLog(const std::string &device, const std::string &tableName); int DeleteDistributedLogTable(const std::string &tableName); @@ -71,7 +73,7 @@ public: int CheckAndCleanDistributedTable(const std::vector &tableNames, std::vector &missingTables); - int CreateDistributedDeviceTable(const std::string &device, const TableInfo &baseTbl); + int CreateDistributedDeviceTable(const std::string &device, const TableInfo &baseTbl, const StoreInfo &info); int CheckQueryObjectLegal(const TableInfo &table, QueryObject &query, const std::string &schemaVersion); @@ -84,6 +86,8 @@ public: int CheckEncryptedOrCorrupted() const; + int GetExistsDeviceList(std::set &devices) const; + private: int GetDataItemForSync(sqlite3_stmt *statement, DataItem &dataItem, bool isGettingDeletedData) const; diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_engine.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_engine.cpp index eb31592a..3282948c 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_engine.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_engine.cpp @@ -392,7 +392,7 @@ int SQLiteSingleVerStorageEngine::ReleaseExecutor(SQLiteSingleVerStorageExecutor Recycle(databaseHandle); handle = nullptr; if (isCorrupted_) { - LOGE("Database is corrupted!"); + LOGE("Database is corrupted or invalid passwd!"); return -E_INVALID_PASSWD_OR_CORRUPTED_DB; // Externally imperceptible, used to terminate migration } return E_OK; diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_executor.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_executor.cpp index d7b13046..91a6cc98 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_executor.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_executor.cpp @@ -24,11 +24,11 @@ #include "parcel.h" #include "platform_specific.h" #include "runtime_context.h" +#include "sqlite_meta_executor.h" #include "sqlite_single_ver_storage_executor_sql.h" namespace DistributedDB { namespace { -const int HASH_KEY_SIZE = 32; // size of SHA256_DIGEST_LENGTH void InitCommitNotifyDataKeyStatus(SingleVerNaturalStoreCommitNotifyData *committedData, const Key &hashKey, const DataOperStatus &dataStatus) @@ -1405,50 +1405,17 @@ int SQLiteSingleVerStorageExecutor::GetAllMetaKeys(std::vector &keys) const return errCode; } - errCode = GetAllKeys(statement, keys); + errCode = SqliteMetaExecutor::GetAllKeys(statement, isMemDb_, keys); SQLiteUtils::ResetStatement(statement, true, errCode); return errCode; } -int SQLiteSingleVerStorageExecutor::GetMetaKeysByKeyPrefix(const std::string &keyPre, - std::set &outKeys) const -{ - sqlite3_stmt *statement = nullptr; - const std::string &sqlStr = (attachMetaMode_ ? SELECT_ATTACH_META_KEYS_BY_PREFIX : SELECT_META_KEYS_BY_PREFIX); - int errCode = SQLiteUtils::GetStatement(dbHandle_, sqlStr, statement); - if (errCode != E_OK) { - LOGE("[SingleVerExe][GetAllKey] Get statement failed:%d", errCode); - return errCode; - } - - Key keyPrefix; - DBCommon::StringToVector(keyPre + '%', keyPrefix); - errCode = SQLiteUtils::BindBlobToStatement(statement, 1, keyPrefix); // 1: bind index for prefix key - if (errCode != E_OK) { - LOGE("[SingleVerExe][GetAllKey] Bind statement failed:%d", errCode); - SQLiteUtils::ResetStatement(statement, true, errCode); - return errCode; - } - - std::vector keys; - errCode = GetAllKeys(statement, keys); - SQLiteUtils::ResetStatement(statement, true, errCode); - for (const auto &it : keys) { - if (it.size() >= keyPre.size() + HASH_KEY_SIZE) { - outKeys.insert({it.begin() + keyPre.size(), it.begin() + keyPre.size() + HASH_KEY_SIZE}); - } else { - LOGW("[SingleVerExe][GetAllKey] Get invalid key, size=%zu", it.size()); - } - } - return errCode; -} - -int SQLiteSingleVerStorageExecutor::GetAllSyncedEntries(const std::string &deviceName, +int SQLiteSingleVerStorageExecutor::GetAllSyncedEntries(const std::string &hashDev, std::vector &entries) const { int errCode = E_OK; sqlite3_stmt *statement = nullptr; - if (deviceName.empty()) { + if (hashDev.empty()) { std::string sql = (executorState_ == ExecutorState::CACHE_ATTACH_MAIN ? SELECT_ALL_SYNC_ENTRIES_FROM_CACHEHANDLE : SELECT_ALL_SYNC_ENTRIES); errCode = SQLiteUtils::GetStatement(dbHandle_, sql, statement); @@ -1465,10 +1432,8 @@ int SQLiteSingleVerStorageExecutor::GetAllSyncedEntries(const std::string &devic return errCode; } - // When removing device data in cache mode, key is "remove", value is deviceID's hash string. - // Therefore, no need to transfer hash string when migrating. - std::string devName = isSyncMigrating_ ? deviceName : DBCommon::TransferHashString(deviceName); - std::vector devVect(devName.begin(), devName.end()); + // deviceName always hash string + std::vector devVect(hashDev.begin(), hashDev.end()); errCode = SQLiteUtils::BindBlobToStatement(statement, 1, devVect, true); // bind the 1st to device. if (errCode != E_OK) { LOGE("Failed to bind the synced device for all entries:%d", errCode); @@ -1514,34 +1479,6 @@ int SQLiteSingleVerStorageExecutor::GetAllEntries(sqlite3_stmt *statement, std:: return errCode; } -int SQLiteSingleVerStorageExecutor::GetAllKeys(sqlite3_stmt *statement, std::vector &keys) const -{ - if (statement == nullptr) { - return -E_INVALID_DB; - } - int errCode; - do { - errCode = SQLiteUtils::StepWithRetry(statement, isMemDb_); - if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { - Key key; - errCode = SQLiteUtils::GetColumnBlobValue(statement, 0, key); - if (errCode != E_OK) { - break; - } - - keys.push_back(std::move(key)); - } else if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { - errCode = E_OK; - break; - } else { - LOGE("SQLite step for getting all keys failed:%d", errCode); - break; - } - } while (true); - - return errCode; -} - int SQLiteSingleVerStorageExecutor::BindSavedSyncData(sqlite3_stmt *statement, const DataItem &dataItem, const Key &hashKey, const SyncDataDevices &devices, bool isUpdate) { @@ -1796,9 +1733,8 @@ int SQLiteSingleVerStorageExecutor::RemoveDeviceData(const std::string &deviceNa goto ERROR; } } else { - // Transfer the device name. - std::string devName = DBCommon::TransferHashString(deviceName); - std::vector devVect(devName.begin(), devName.end()); + // device name always hash string. + std::vector devVect(deviceName.begin(), deviceName.end()); errCode = SQLiteUtils::GetStatement(dbHandle_, REMOVE_DEV_DATA_SQL, statement); if (errCode != E_OK) { goto ERROR; @@ -2236,20 +2172,90 @@ uint64_t SQLiteSingleVerStorageExecutor::GetLogFileSize() const int SQLiteSingleVerStorageExecutor::GetExistsDevicesFromMeta(std::set &devices) { - int errCode = GetMetaKeysByKeyPrefix(DBConstant::DEVICEID_PREFIX_KEY, devices); + return SqliteMetaExecutor::GetExistsDevicesFromMeta(dbHandle_, + attachMetaMode_ ? SqliteMetaExecutor::MetaMode::KV_ATTACH : SqliteMetaExecutor::MetaMode::KV, + isMemDb_, devices); +} + +int SQLiteSingleVerStorageExecutor::UpdateKey(const UpdateKeyCallback &callback) +{ + if (dbHandle_ == nullptr) { + return -E_INVALID_DB; + } + UpdateContext context; + context.callback = callback; + int errCode = CreateFuncUpdateKey(context, &Translate, &CalHashKey); if (errCode != E_OK) { - LOGE("Get meta data key failed. err=%d", errCode); return errCode; } - errCode = GetMetaKeysByKeyPrefix(DBConstant::QUERY_SYNC_PREFIX_KEY, devices); + int executeErrCode = SQLiteUtils::ExecuteRawSQL(dbHandle_, UPDATE_SYNC_DATA_KEY_SQL); + context.callback = nullptr; + errCode = CreateFuncUpdateKey(context, nullptr, nullptr); + if (context.errCode != E_OK) { + return context.errCode; + } + if (executeErrCode != E_OK) { + return executeErrCode; + } if (errCode != E_OK) { - LOGE("Get meta data key failed. err=%d", errCode); return errCode; } - errCode = GetMetaKeysByKeyPrefix(DBConstant::DELETE_SYNC_PREFIX_KEY, devices); - if (errCode != E_OK) { - LOGE("Get meta data key failed. err=%d", errCode); + return E_OK; +} + +int SQLiteSingleVerStorageExecutor::CreateFuncUpdateKey(UpdateContext &context, + void(*translateFunc)(sqlite3_context *ctx, int argc, sqlite3_value **argv), + void(*calHashFunc)(sqlite3_context *ctx, int argc, sqlite3_value **argv)) const +{ + int errCode = sqlite3_create_function_v2(dbHandle_, FUNC_NAME_TRANSLATE_KEY, 1, SQLITE_UTF8 | SQLITE_DETERMINISTIC, + &context, translateFunc, nullptr, nullptr, nullptr); + if (errCode != SQLITE_OK) { + LOGE("[SqlSinExe][UpdateKey] Create func=translate_key failed=%d", errCode); + return SQLiteUtils::MapSQLiteErrno(errCode); } - return errCode; + errCode = sqlite3_create_function_v2(dbHandle_, FUNC_NAME_CAL_HASH_KEY, 1, SQLITE_UTF8 | SQLITE_DETERMINISTIC, + &context, calHashFunc, nullptr, nullptr, nullptr); + if (errCode != SQLITE_OK) { + LOGE("[SqlSinExe][UpdateKey] Create func=translate_key failed=%d", errCode); + return SQLiteUtils::MapSQLiteErrno(errCode); + } + return E_OK; +} + +void SQLiteSingleVerStorageExecutor::Translate(sqlite3_context *ctx, int argc, sqlite3_value **argv) +{ + if (ctx == nullptr || argc != 1 || argv == nullptr) { // i parameters, which are key + LOGW("[SqlSinExe][Translate] invalid param=%d", argc); + return; + } + auto context = static_cast(sqlite3_user_data(ctx)); + auto keyBlob = static_cast(sqlite3_value_blob(argv[0])); + int keyBlobLen = sqlite3_value_bytes(argv[0]); + Key oldKey; + if (keyBlob != nullptr && keyBlobLen > 0) { + oldKey = Key(keyBlob, keyBlob + keyBlobLen); + } + Key newKey; + context->callback(oldKey, newKey); + if (newKey.size() >= DBConstant::MAX_KEY_SIZE || newKey.empty()) { + LOGE("[SqlSinExe][Translate] invalid key len=%zu", newKey.size()); + context->errCode = -E_INVALID_ARGS; + sqlite3_result_error(ctx, "Update key is invalid", -1); + return; + } + context->newKey = newKey; + sqlite3_result_blob(ctx, newKey.data(), static_cast(newKey.size()), SQLITE_TRANSIENT); +} + +void SQLiteSingleVerStorageExecutor::CalHashKey(sqlite3_context *ctx, int argc, sqlite3_value **argv) +{ + if (ctx == nullptr || argc != 1 || argv == nullptr) { + LOGW("[SqlSinExe][Translate] invalid param=%d", argc); + return; + } + auto context = static_cast(sqlite3_user_data(ctx)); + Key hashKey; + DBCommon::CalcValueHash(context->newKey, hashKey); + sqlite3_result_blob(ctx, hashKey.data(), static_cast(hashKey.size()), SQLITE_TRANSIENT); } } // namespace DistributedDB diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_executor.h b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_executor.h index 255792cc..57a3a162 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_executor.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_executor.h @@ -121,9 +121,8 @@ public: // Get all the meta keys. int GetAllMetaKeys(std::vector &keys) const; - int GetMetaKeysByKeyPrefix(const std::string &keyPre, std::set &outKeys) const; - int GetAllSyncedEntries(const std::string &deviceName, std::vector &entries) const; + int GetAllSyncedEntries(const std::string &hashDev, std::vector &entries) const; int SaveSyncDataItem(DataItem &dataItem, const DeviceInfo &deviceInfo, Timestamp &maxStamp, SingleVerNaturalStoreCommitNotifyData *committedData, bool isPermitForceWrite = true); @@ -136,7 +135,7 @@ public: int RemoveDeviceData(const std::string &deviceName); - int RemoveDeviceDataInCacheMode(const std::string &deviceName, bool isNeedNotify, uint64_t recordVersion) const; + int RemoveDeviceDataInCacheMode(const std::string &hashDev, bool isNeedNotify, uint64_t recordVersion) const; void InitCurrentMaxStamp(Timestamp &maxStamp); @@ -251,6 +250,8 @@ public: int GetExistsDevicesFromMeta(std::set &devices); + int UpdateKey(const UpdateKeyCallback &callback); + private: struct SaveRecordStatements { sqlite3_stmt *queryStatement = nullptr; @@ -265,6 +266,12 @@ private: } }; + struct UpdateContext { + int errCode = E_OK; + Key newKey; + UpdateKeyCallback callback; + }; + void PutIntoCommittedData(const DataItem &itemPut, const DataItem &itemGet, const DataOperStatus &status, SingleVerNaturalStoreCommitNotifyData *committedData); @@ -301,8 +308,6 @@ private: int InitResultSet(QueryObject &queryObj, sqlite3_stmt *&countStmt); - int GetAllKeys(sqlite3_stmt *statement, std::vector &keys) const; - int GetAllEntries(sqlite3_stmt *statement, std::vector &entries) const; int BindPutKvData(sqlite3_stmt *statement, const Key &key, const Value &value, Timestamp timestamp, @@ -396,6 +401,14 @@ private: int CheckMissQueryDataItem(sqlite3_stmt *stmt, const std::string &deviceName, DataItem &item); + int CreateFuncUpdateKey(UpdateContext &context, + void(*translateFunc)(sqlite3_context *ctx, int argc, sqlite3_value **argv), + void(*calHashFunc)(sqlite3_context *ctx, int argc, sqlite3_value **argv)) const; + + static void Translate(sqlite3_context *ctx, int argc, sqlite3_value **argv); + + static void CalHashKey(sqlite3_context *ctx, int argc, sqlite3_value **argv); + sqlite3_stmt *getSyncStatement_; sqlite3_stmt *getResultRowIdStatement_; sqlite3_stmt *getResultEntryStatement_; diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_executor_cache.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_executor_cache.cpp index af15b371..82ec7a98 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_executor_cache.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_executor_cache.cpp @@ -77,12 +77,11 @@ int SQLiteSingleVerStorageExecutor::ResetForMigrateCacheData() return CheckCorruptedStatus(errCode); } -int SQLiteSingleVerStorageExecutor::RemoveDeviceDataInCacheMode(const std::string &deviceName, +int SQLiteSingleVerStorageExecutor::RemoveDeviceDataInCacheMode(const std::string &hashDev, bool isNeedNotify, uint64_t recordVersion) const { - // Transfer the device name. - std::string devName = DBCommon::TransferHashString(deviceName); - std::vector devVect(devName.begin(), devName.end()); + // device name always hash string. + std::vector devVect(hashDev.begin(), hashDev.end()); Key hashKey; int errCode = DBCommon::CalcValueHash(REMOVE_DEVICE_DATA_KEY, hashKey); diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_executor_sql.h b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_executor_sql.h index 5fceeaeb..17ad5183 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_executor_sql.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_executor_sql.h @@ -230,6 +230,13 @@ namespace DistributedDB { const std::string GET_SYNC_DATA_TIRGGER_SQL = "SELECT name FROM SQLITE_MASTER WHERE TYPE = 'trigger' AND TBL_NAME = 'sync_data' AND name like ?;"; + constexpr const char *UPDATE_SYNC_DATA_KEY_SQL = + "UPDATE sync_data SET key=translate_key(key), hash_key=cal_hash_key(key) WHERE flag&0x01=0"; + + constexpr const char *FUNC_NAME_TRANSLATE_KEY = "translate_key"; + + constexpr const char *FUNC_NAME_CAL_HASH_KEY = "cal_hash_key"; + const int BIND_KV_KEY_INDEX = 1; const int BIND_KV_VAL_INDEX = 2; const int BIND_LOCAL_TIMESTAMP_INDEX = 3; diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_utils.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_utils.cpp index 687b40b4..ec0dac0e 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_utils.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_utils.cpp @@ -248,12 +248,6 @@ int SQLiteUtils::BindTextToStatement(sqlite3_stmt *statement, int index, const s return -E_INVALID_ARGS; } - // Check empty value. - if (str.empty()) { - sqlite3_bind_null(statement, index); - return E_OK; - } - int errCode = sqlite3_bind_text(statement, index, str.c_str(), str.length(), SQLITE_TRANSIENT); if (errCode != SQLITE_OK) { LOGE("[SQLiteUtil][Bind text]Failed to bind the value:%d", errCode); @@ -1097,20 +1091,31 @@ int SQLiteUtils::SetUserVer(sqlite3 *db, int version) int SQLiteUtils::MapSQLiteErrno(int errCode) { - if (errCode == SQLITE_OK) { - return E_OK; - } else if (errCode == SQLITE_IOERR) { - if (errno == EKEYREVOKED) { - return -E_EKEYREVOKED; - } - } else if (errCode == SQLITE_CORRUPT || errCode == SQLITE_NOTADB) { - return -E_INVALID_PASSWD_OR_CORRUPTED_DB; - } else if (errCode == SQLITE_LOCKED || errCode == SQLITE_BUSY) { - return -E_BUSY; - } else if (errCode == SQLITE_ERROR && errno == EKEYREVOKED) { - return -E_EKEYREVOKED; - } else if (errCode == SQLITE_AUTH) { - return -E_DENIED_SQL; + switch (errCode) { + case SQLITE_OK: + return E_OK; + case SQLITE_IOERR: + if (errno == EKEYREVOKED) { + return -E_EKEYREVOKED; + } + break; + case SQLITE_CORRUPT: + case SQLITE_NOTADB: + return -E_INVALID_PASSWD_OR_CORRUPTED_DB; + case SQLITE_LOCKED: + case SQLITE_BUSY: + return -E_BUSY; + case SQLITE_ERROR: + if (errno == EKEYREVOKED) { + return -E_EKEYREVOKED; + } + break; + case SQLITE_AUTH: + return -E_DENIED_SQL; + case SQLITE_CONSTRAINT: + return -E_CONSTRAINT; + default: + break; } return -errCode; } diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/storage_engine.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/storage_engine.cpp index 8a8e8cda..84e6cb81 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/storage_engine.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/storage_engine.cpp @@ -42,61 +42,67 @@ StorageEngine::~StorageEngine() CloseExecutor(); } -int StorageEngine::Init() +int StorageEngine::InitReadWriteExecutors() { - if (isInitialized_.load()) { - LOGD("Storage engine has been initialized!"); - return E_OK; - } - int errCode = E_OK; - { - std::scoped_lock initLock(writeMutex_, readMutex_); - // only for create the database avoid the minimum number is 0. - StorageExecutor *handle = nullptr; - if (engineAttr_.minReadNum == 0 && engineAttr_.minWriteNum == 0) { - errCode = CreateNewExecutor(true, handle); - if (errCode != E_OK) { - goto END; - } - - if (handle != nullptr) { - delete handle; - handle = nullptr; - } + std::scoped_lock initLock(writeMutex_, readMutex_); + // only for create the database avoid the minimum number is 0. + StorageExecutor *handle = nullptr; + if (engineAttr_.minReadNum == 0 && engineAttr_.minWriteNum == 0) { + errCode = CreateNewExecutor(true, handle); + if (errCode != E_OK) { + return errCode; } - for (uint32_t i = 0; i < engineAttr_.minWriteNum; i++) { + if (handle != nullptr) { + delete handle; handle = nullptr; - errCode = CreateNewExecutor(true, handle); - if (errCode != E_OK) { - goto END; - } - AddStorageExecutor(handle); } + } - for (uint32_t i = 0; i < engineAttr_.minReadNum; i++) { - handle = nullptr; - errCode = CreateNewExecutor(false, handle); - if (errCode != E_OK) { - goto END; - } - AddStorageExecutor(handle); + for (uint32_t i = 0; i < engineAttr_.minWriteNum; i++) { + handle = nullptr; + errCode = CreateNewExecutor(true, handle); + if (errCode != E_OK) { + return errCode; } + AddStorageExecutor(handle); } -END: + for (uint32_t i = 0; i < engineAttr_.minReadNum; i++) { + handle = nullptr; + errCode = CreateNewExecutor(false, handle); + if (errCode != E_OK) { + return errCode; + } + AddStorageExecutor(handle); + } + return E_OK; +} + + +int StorageEngine::Init() +{ + if (isInitialized_.load()) { + LOGD("Storage engine has been initialized!"); + return E_OK; + } + + int errCode = InitReadWriteExecutors(); if (errCode == E_OK) { isInitialized_.store(true); + initCondition_.notify_all(); return E_OK; } else if (errCode == -E_EKEYREVOKED) { // Assumed file system has classification function, can only get one write handle std::unique_lock lock(writeMutex_); if (!writeIdleList_.empty() || !writeUsingList_.empty()) { isInitialized_.store(true); + initCondition_.notify_all(); return E_OK; } } + initCondition_.notify_all(); Release(); return errCode; } @@ -109,10 +115,16 @@ StorageExecutor *StorageEngine::FindExecutor(bool writable, OperatePerm perm, in return nullptr; } - if (!isInitialized_.load()) { - LOGE("Storage engine is not initialized"); - errCode = -E_BUSY; // Usually in reinitialize engine, return BUSY - return nullptr; + { + std::unique_lock lock(initMutex_); + bool result = initCondition_.wait_for(lock, std::chrono::seconds(waitTime), [this]() { + return isInitialized_.load(); + }); + if (!result || !isInitialized_.load()) { + LOGE("Storage engine is not initialized"); + errCode = -E_BUSY; // Usually in reinitialize engine, return BUSY + return nullptr; + } } if (writable) { diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/storage_engine.h b/kv_store/frameworks/libs/distributeddb/storage/src/storage_engine.h index 1a9dd227..cb9a7d21 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/storage_engine.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/storage_engine.h @@ -89,6 +89,8 @@ protected: static bool CheckEngineAttr(const StorageEngineAttr &poolSize); + int InitReadWriteExecutors(); + StorageEngineAttr engineAttr_; bool isUpdated_; std::atomic isMigrating_; @@ -114,6 +116,8 @@ private: static const int MAX_WRITE_SIZE; static const int MAX_READ_SIZE; + std::mutex initMutex_; + std::condition_variable initCondition_; std::atomic isInitialized_; OperatePerm perm_; bool operateAbort_; diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sync_able_engine.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sync_able_engine.cpp index 0c5e86ca..e6540734 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sync_able_engine.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sync_able_engine.cpp @@ -66,7 +66,7 @@ void SyncAbleEngine::Close() void SyncAbleEngine::EnableAutoSync(bool enable) { - if (!started_) { + if (NeedStartSyncer()) { StartSyncer(); } return syncer_.EnableAutoSync(enable); @@ -85,7 +85,7 @@ int SyncAbleEngine::DisableManualSync(void) // Get The current virtual timestamp uint64_t SyncAbleEngine::GetTimestamp() { - if (!started_) { + if (NeedStartSyncer()) { StartSyncer(); } return syncer_.GetTimestamp(); @@ -93,7 +93,7 @@ uint64_t SyncAbleEngine::GetTimestamp() int SyncAbleEngine::EraseDeviceWaterMark(const std::string &deviceId, bool isNeedHash, const std::string &tableName) { - if (!started_) { + if (NeedStartSyncer()) { StartSyncer(); } return syncer_.EraseDeviceWaterMark(deviceId, isNeedHash, tableName); @@ -176,6 +176,15 @@ void SyncAbleEngine::StopSyncerWithNoLock(bool isClosedOperation) void SyncAbleEngine::UserChangeHandle() { + if (store_ == nullptr) { + LOGD("[SyncAbleEngine] RDB got null sync interface in userChange."); + return; + } + bool isSyncDualTupleMode = store_->GetDbProperties().GetBoolProp(DBProperties::SYNC_DUAL_TUPLE_MODE, false); + if (!isSyncDualTupleMode) { + LOGD("[SyncAbleEngine] no use syncDualTupleMode, abort userChange"); + return; + } std::unique_lock lock(syncerOperateLock_); if (closed_) { LOGI("RDB is already closed"); @@ -270,4 +279,19 @@ int SyncAbleEngine::RemoteQuery(const std::string &device, const RemoteCondition } return syncer_.RemoteQuery(device, condition, timeout, connectionId, result); } + +bool SyncAbleEngine::NeedStartSyncer() const +{ + // don't start when check callback got not active + // equivalent to !(!isSyncNeedActive_ && isSyncModuleActiveCheck_) + return !started_ && (isSyncNeedActive_ || !isSyncModuleActiveCheck_); +} + +int SyncAbleEngine::GetHashDeviceId(const std::string &clientId, std::string &hashDevId) +{ + if (NeedStartSyncer()) { + StartSyncer(); + } + return syncer_.GetHashDeviceId(clientId, hashDevId); +} } diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sync_able_engine.h b/kv_store/frameworks/libs/distributeddb/storage/src/sync_able_engine.h index 9afc0ff9..3b45461f 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sync_able_engine.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sync_able_engine.h @@ -54,6 +54,8 @@ public: int RemoteQuery(const std::string &device, const RemoteCondition &condition, uint64_t timeout, uint64_t connectionId, std::shared_ptr &result); + + int GetHashDeviceId(const std::string &clientId, std::string &hashDevId); private: // Start syncer int StartSyncer(bool isCheckSyncActive = false, bool isNeedActive = true); @@ -75,6 +77,8 @@ private: void ChangeUserListener(); + bool NeedStartSyncer() const; + SyncerProxy syncer_; // use for sync Interactive std::atomic started_; std::atomic closed_; diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sync_able_kvdb.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sync_able_kvdb.cpp index 711621e3..b16a2807 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sync_able_kvdb.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sync_able_kvdb.cpp @@ -92,7 +92,7 @@ int SyncAbleKvDB::Sync(const ISyncer::SyncParma &parma, uint64_t connectionId) void SyncAbleKvDB::EnableAutoSync(bool enable) { - if (!started_) { + if (NeedStartSyncer()) { StartSyncer(); } return syncer_.EnableAutoSync(enable); @@ -100,7 +100,7 @@ void SyncAbleKvDB::EnableAutoSync(bool enable) void SyncAbleKvDB::WakeUpSyncer() { - if (!started_) { + if (NeedStartSyncer()) { StartSyncer(); } } @@ -232,6 +232,12 @@ void SyncAbleKvDB::UserChangeHandle() LOGF("KvDB got null sync interface."); return; } + bool isSyncDualTupleMode = syncInterface->GetDbProperties(). + GetBoolProp(KvDBProperties::SYNC_DUAL_TUPLE_MODE, false); + if (!isSyncDualTupleMode) { + LOGD("[SyncAbleKvDB] no use syncDualTupleMode, abort userChange"); + return; + } std::unique_lock lock(syncerOperateLock_); if (closed_) { LOGI("kvDB is already closed"); @@ -264,7 +270,7 @@ void SyncAbleKvDB::ChangeUserListener() // Get The current virtual timestamp uint64_t SyncAbleKvDB::GetTimestamp() { - if (!started_ && !isSyncModuleActiveCheck_) { + if (NeedStartSyncer()) { StartSyncer(); } return syncer_.GetTimestamp(); @@ -278,7 +284,7 @@ uint32_t SyncAbleKvDB::GetAppendedLen() const int SyncAbleKvDB::EraseDeviceWaterMark(const std::string &deviceId, bool isNeedHash) { - if (!started_) { + if (NeedStartSyncer()) { StartSyncer(); } return syncer_.EraseDeviceWaterMark(deviceId, isNeedHash); @@ -378,11 +384,17 @@ void SyncAbleKvDB::NotifyRemotePushFinishedInner(const std::string &targetId) co int SyncAbleKvDB::SetSyncRetry(bool isRetry) { + if (NeedStartSyncer()) { + StartSyncer(); + } return syncer_.SetSyncRetry(isRetry); } int SyncAbleKvDB::SetEqualIdentifier(const std::string &identifier, const std::vector &targets) { + if (NeedStartSyncer()) { + StartSyncer(); + } return syncer_.SetEqualIdentifier(identifier, targets); } @@ -401,4 +413,19 @@ int SyncAbleKvDB::GetSyncDataSize(const std::string &device, size_t &size) const { return syncer_.GetSyncDataSize(device, size); } + +bool SyncAbleKvDB::NeedStartSyncer() const +{ + // don't start when check callback got not active + // equivalent to !(!isSyncNeedActive_ && isSyncModuleActiveCheck_) + return !started_ && (isSyncNeedActive_ || !isSyncModuleActiveCheck_); +} + +int SyncAbleKvDB::GetHashDeviceId(const std::string &clientId, std::string &hashDevId) +{ + if (NeedStartSyncer()) { + StartSyncer(); + } + return syncer_.GetHashDeviceId(clientId, hashDevId); +} } diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sync_able_kvdb.h b/kv_store/frameworks/libs/distributeddb/storage/src/sync_able_kvdb.h index 86171bba..c5e08092 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sync_able_kvdb.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sync_able_kvdb.h @@ -87,6 +87,8 @@ public: int GetSyncDataSize(const std::string &device, size_t &size) const; + int GetHashDeviceId(const std::string &clientId, std::string &hashDevId); + protected: virtual IKvDBSyncInterface *GetSyncInterface() = 0; @@ -119,6 +121,8 @@ protected: private: int RegisterEventType(EventType type); + bool NeedStartSyncer() const; + SyncerProxy syncer_; std::atomic started_; std::atomic closed_; diff --git a/kv_store/frameworks/libs/distributeddb/syncer/include/isyncer.h b/kv_store/frameworks/libs/distributeddb/syncer/include/isyncer.h index 42a3320d..6f970639 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/include/isyncer.h +++ b/kv_store/frameworks/libs/distributeddb/syncer/include/isyncer.h @@ -123,6 +123,8 @@ public: uint64_t timeout, uint64_t connectionId, std::shared_ptr &result) = 0; virtual int GetSyncDataSize(const std::string &device, size_t &size) const = 0; + + virtual int GetHashDeviceId(const std::string &clientId, std::string &hashDevId) = 0; }; } // namespace DistributedDB diff --git a/kv_store/frameworks/libs/distributeddb/syncer/include/syncer_proxy.h b/kv_store/frameworks/libs/distributeddb/syncer/include/syncer_proxy.h index 1d6294af..2725237a 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/include/syncer_proxy.h +++ b/kv_store/frameworks/libs/distributeddb/syncer/include/syncer_proxy.h @@ -107,6 +107,7 @@ public: int GetSyncDataSize(const std::string &device, size_t &size) const override; + int GetHashDeviceId(const std::string &clientId, std::string &hashDevId) override; private: std::mutex syncerLock_; std::shared_ptr syncer_; diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/generic_syncer.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/generic_syncer.cpp index 8227f3c2..e018e014 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/generic_syncer.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/generic_syncer.cpp @@ -284,10 +284,26 @@ int GenericSyncer::StopSync(uint64_t connectionId) uint64_t GenericSyncer::GetTimestamp() { - if (timeHelper_ == nullptr) { + std::shared_ptr timeHelper = nullptr; + ISyncInterface *storage = nullptr; + { + std::lock_guard lock(syncerLock_); + timeHelper = timeHelper_; + if (syncInterface_ != nullptr) { + storage = syncInterface_; + storage->IncRefCount(); + } + } + if (storage == nullptr) { + return TimeHelper::GetSysCurrentTime(); + } + if (timeHelper == nullptr) { + storage->DecRefCount(); return TimeHelper::GetSysCurrentTime(); } - return timeHelper_->GetTime(); + uint64_t timestamp = timeHelper->GetTime(); + storage->DecRefCount(); + return timestamp; } void GenericSyncer::QueryAutoSync(const InternalSyncParma ¶m) @@ -446,13 +462,11 @@ bool GenericSyncer::IsValidMode(int mode) const return true; } -int GenericSyncer::SyncConditionCheck(QuerySyncObject &query, int mode, bool isQuerySync, - const std::vector &devices) const +int GenericSyncer::SyncConditionCheck(const SyncParma ¶m, const ISyncEngine *engine, ISyncInterface *storage) const { - (void)query; - (void)mode; - (void)isQuerySync; - (void)(devices); + (void)param; + (void)engine; + (void)storage; return E_OK; } @@ -785,20 +799,34 @@ int GenericSyncer::StatusCheck() const int GenericSyncer::SyncPreCheck(const SyncParma ¶m) const { - std::lock_guard lock(syncerLock_); - int errCode = StatusCheck(); - if (errCode != E_OK) { - return errCode; - } - if (!IsValidDevices(param.devices) || !IsValidMode(param.mode)) { - return -E_INVALID_ARGS; - } - if (IsQueuedManualSyncFull(param.mode, param.wait)) { - LOGE("[Syncer] -E_BUSY"); - return -E_BUSY; + ISyncEngine *engine = nullptr; + ISyncInterface *storage = nullptr; + int errCode = E_OK; + { + std::lock_guard lock(syncerLock_); + errCode = StatusCheck(); + if (errCode != E_OK) { + return errCode; + } + if (!IsValidDevices(param.devices) || !IsValidMode(param.mode)) { + return -E_INVALID_ARGS; + } + if (IsQueuedManualSyncFull(param.mode, param.wait)) { + LOGE("[Syncer] -E_BUSY"); + return -E_BUSY; + } + storage = syncInterface_; + engine = syncEngine_; + if (storage == nullptr || engine == nullptr) { + return -E_BUSY; + } + storage->IncRefCount(); + RefObject::IncObjRef(engine); } - QuerySyncObject syncQuery = param.syncQuery; - return SyncConditionCheck(syncQuery, param.mode, param.isQuerySync, param.devices); + errCode = SyncConditionCheck(param, engine, storage); + storage->DecRefCount(); + RefObject::DecObjRef(engine); + return errCode; } void GenericSyncer::InitSyncOperation(SyncOperation *operation, const SyncParma ¶m) @@ -1023,4 +1051,9 @@ bool GenericSyncer::IsNeedActive(ISyncInterface *syncInterface) } return true; } + +int GenericSyncer::GetHashDeviceId(const std::string &clientId, std::string &hashDevId) +{ + return -E_NOT_SUPPORT; +} } // namespace DistributedDB diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/generic_syncer.h b/kv_store/frameworks/libs/distributeddb/syncer/src/generic_syncer.h index 7d89adbf..f2146216 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/generic_syncer.h +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/generic_syncer.h @@ -104,6 +104,7 @@ public: int GetSyncDataSize(const std::string &device, size_t &size) const override; + int GetHashDeviceId(const std::string &clientId, std::string &hashDevId) override; protected: // trigger query auto sync or auto subscribe @@ -143,8 +144,7 @@ protected: // Check if the mode arg is valid bool IsValidMode(int mode) const; - virtual int SyncConditionCheck(QuerySyncObject &query, int mode, bool isQuerySync, - const std::vector &devices) const; + virtual int SyncConditionCheck(const SyncParma ¶m, const ISyncEngine *engine, ISyncInterface *storage) const; // Check if the devices arg is valid bool IsValidDevices(const std::vector &devices) const; diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/isync_task_context.h b/kv_store/frameworks/libs/distributeddb/syncer/src/isync_task_context.h index 3c51184b..e489afd5 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/isync_task_context.h +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/isync_task_context.h @@ -68,7 +68,7 @@ public: // Move to next target to sync virtual void MoveToNextTarget() = 0; - virtual int GetNextTarget(bool isNeedSetFinished) = 0; + virtual int GetNextTarget() = 0; // Get the current task syncId virtual uint32_t GetSyncId() const = 0; diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/meta_data.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/meta_data.cpp index 5bfc2b5a..ffbad817 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/meta_data.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/meta_data.cpp @@ -30,6 +30,7 @@ namespace { const int STR_TO_LL_BY_DEVALUE = 10; // store local timeoffset;this is a special key; const std::string LOCALTIME_OFFSET_KEY = "localTimeOffset"; + const char *CLIENT_ID_PREFIX_KEY = "clientId"; } Metadata::Metadata() @@ -124,7 +125,7 @@ int Metadata::SavePeerWaterMark(const DeviceID &deviceId, uint64_t inValue, bool GetMetaDataValue(deviceId, metadata, isNeedHash); metadata.peerWaterMark = inValue; LOGD("Metadata::SavePeerWaterMark = %" PRIu64, inValue); - return SaveMetaDataValue(deviceId, metadata); + return SaveMetaDataValue(deviceId, metadata, isNeedHash); } int Metadata::SaveLocalTimeOffset(TimeOffset timeOffset) @@ -160,9 +161,9 @@ int Metadata::EraseDeviceWaterMark(const std::string &deviceId, bool isNeedHash, // try to erase all the waterMark // erase deleteSync recv waterMark WaterMark waterMark = 0; - int errCodeDeleteSync = SetRecvDeleteSyncWaterMark(deviceId, waterMark); + int errCodeDeleteSync = SetRecvDeleteSyncWaterMark(deviceId, waterMark, isNeedHash); // erase querySync recv waterMark - int errCodeQuerySync = ResetRecvQueryWaterMark(deviceId, tableName); + int errCodeQuerySync = ResetRecvQueryWaterMark(deviceId, tableName, isNeedHash); // peerWaterMark must be erased at last int errCode = SavePeerWaterMark(deviceId, 0, isNeedHash); if (errCode != E_OK) { @@ -194,7 +195,7 @@ Timestamp Metadata::GetLastLocalTime() const return lastLocalTime_; } -int Metadata::SaveMetaDataValue(const DeviceID &deviceId, const MetaDataValue &inValue) +int Metadata::SaveMetaDataValue(const DeviceID &deviceId, const MetaDataValue &inValue, bool isNeedHash) { std::vector value; int errCode = SerializeMetaData(inValue, value); @@ -203,7 +204,7 @@ int Metadata::SaveMetaDataValue(const DeviceID &deviceId, const MetaDataValue &i } DeviceID hashDeviceId; - GetHashDeviceId(deviceId, hashDeviceId, true); + GetHashDeviceId(deviceId, hashDeviceId, isNeedHash); std::vector key; DBCommon::StringToVector(hashDeviceId, key); errCode = SetMetadataToDb(key, value); @@ -232,12 +233,11 @@ int Metadata::SerializeMetaData(const MetaDataValue &inValue, std::vector &inValue, MetaDataValue &outValue) const +int Metadata::DeSerializeMetaData(const std::vector &inValue, MetaDataValue &outValue) { if (inValue.empty()) { return -E_INVALID_ARGS; } - errno_t err = memcpy_s(&outValue, sizeof(MetaDataValue), inValue.data(), inValue.size()); if (err != EOK) { return -E_SECUREC_ERROR; @@ -457,14 +457,14 @@ int Metadata::GetRecvDeleteSyncWaterMark(const DeviceID &deviceId, WaterMark &wa return E_OK; } -int Metadata::SetRecvDeleteSyncWaterMark(const DeviceID &deviceId, const WaterMark &waterMark) +int Metadata::SetRecvDeleteSyncWaterMark(const DeviceID &deviceId, const WaterMark &waterMark, bool isNeedHash) { - return querySyncWaterMarkHelper_.SetRecvDeleteSyncWaterMark(deviceId, waterMark); + return querySyncWaterMarkHelper_.SetRecvDeleteSyncWaterMark(deviceId, waterMark, isNeedHash); } -int Metadata::ResetRecvQueryWaterMark(const DeviceID &deviceId, const std::string &tableName) +int Metadata::ResetRecvQueryWaterMark(const DeviceID &deviceId, const std::string &tableName, bool isNeedHash) { - return querySyncWaterMarkHelper_.ResetRecvQueryWaterMark(deviceId, tableName); + return querySyncWaterMarkHelper_.ResetRecvQueryWaterMark(deviceId, tableName, isNeedHash); } void Metadata::GetDbCreateTime(const DeviceID &deviceId, uint64_t &outValue) @@ -511,7 +511,7 @@ int Metadata::ResetMetaDataAfterRemoveData(const DeviceID &deviceId) GetHashDeviceId(deviceId, hashDeviceId, true); if (metadataMap_.find(hashDeviceId) != metadataMap_.end()) { metadata = metadataMap_[hashDeviceId]; - metadata.clearDeviceDataMark = 0; + metadata.clearDeviceDataMark = 0; // clear mark return SaveMetaDataValue(deviceId, metadata); } return -E_NOT_FOUND; @@ -570,4 +570,50 @@ void Metadata::RemoveQueryFromRecordSet(const DeviceID &deviceId, const std::str iter->second.erase(hashqueryId); } } + +int Metadata::SaveClientId(const std::string &deviceId, const std::string &clientId) +{ + { + // already save in cache + std::lock_guard autoLock(clientIdLock_); + if (clientIdCache_[deviceId] == clientId) { + return E_OK; + } + } + std::string keyStr; + keyStr.append(CLIENT_ID_PREFIX_KEY).append(clientId); + std::string valueStr = DBCommon::TransferHashString(deviceId); + Key key; + DBCommon::StringToVector(keyStr, key); + Value value; + DBCommon::StringToVector(valueStr, value); + int errCode = SetMetadataToDb(key, value); + if (errCode != E_OK) { + return errCode; + } + std::lock_guard autoLock(clientIdLock_); + clientIdCache_[deviceId] = clientId; + return E_OK; +} + +int Metadata::GetHashDeviceId(const std::string &clientId, std::string &hashDevId) +{ + // don't use cache here avoid invalid cache + std::string keyStr; + keyStr.append(CLIENT_ID_PREFIX_KEY).append(clientId); + Key key; + DBCommon::StringToVector(keyStr, key); + Value value; + int errCode = GetMetadataFromDb(key, value); + if (errCode == -E_NOT_FOUND) { + LOGD("[Metadata] not found clientId"); + return -E_NOT_SUPPORT; + } + if (errCode != E_OK) { + LOGE("[Metadata] reload clientId failed %d", errCode); + return errCode; + } + DBCommon::VectorToString(value, hashDevId); + return E_OK; +} } // namespace DistributedDB \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/meta_data.h b/kv_store/frameworks/libs/distributeddb/syncer/src/meta_data.h index 26e2287b..a73d60fa 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/meta_data.h +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/meta_data.h @@ -93,7 +93,7 @@ public: // if the sendWatermark less than device watermark int GetSendDeleteSyncWaterMark(const std::string &deviceId, WaterMark &waterMark, bool isAutoLift = true); - int SetRecvDeleteSyncWaterMark(const std::string &deviceId, const WaterMark &waterMark); + int SetRecvDeleteSyncWaterMark(const std::string &deviceId, const WaterMark &waterMark, bool isNeedHash = true); // the deleteSync's recvWatermark will increase by the device watermark // if the recvWatermark less than device watermark @@ -111,16 +111,20 @@ public: uint64_t GetQueryLastTimestamp(const DeviceID &deviceId, const std::string &queryId) const; void RemoveQueryFromRecordSet(const DeviceID &deviceId, const std::string &queryId); + + int SaveClientId(const std::string &deviceId, const std::string &clientId); + + int GetHashDeviceId(const std::string &clientId, std::string &hashDevId); private: - int SaveMetaDataValue(const DeviceID &deviceId, const MetaDataValue &inValue); + int SaveMetaDataValue(const DeviceID &deviceId, const MetaDataValue &inValue, bool isNeedHash = true); // sync module need hash devices id void GetMetaDataValue(const DeviceID &deviceId, MetaDataValue &outValue, bool isNeedHash); - int SerializeMetaData(const MetaDataValue &inValue, std::vector &outValue); + static int SerializeMetaData(const MetaDataValue &inValue, std::vector &outValue); - int DeSerializeMetaData(const std::vector &inValue, MetaDataValue &outValue) const; + static int DeSerializeMetaData(const std::vector &inValue, MetaDataValue &outValue); int GetMetadataFromDb(const std::vector &key, std::vector &outValue) const; @@ -143,7 +147,7 @@ private: int LoadDeviceIdDataToMap(const Key &key); // reset the waterMark to zero - int ResetRecvQueryWaterMark(const DeviceID &deviceId, const std::string &tableName = ""); + int ResetRecvQueryWaterMark(const DeviceID &deviceId, const std::string &tableName, bool isNeedHash); // store localTimeOffset in ram; if change, should add a lock first, change here and metadata, // then release lock @@ -167,6 +171,9 @@ private: // queryId is not in set while key is not found from db first time, and return lastTimestamp = INT64_MAX // if query is in set return 0 while not found from db, means already sync before, don't trigger again mutable std::map> queryIdMap_; + + std::mutex clientIdLock_; + std::map clientIdCache_; }; } // namespace DistributedDB #endif diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/query_sync_water_mark_helper.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/query_sync_water_mark_helper.cpp index 70c37ffa..575d8c23 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/query_sync_water_mark_helper.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/query_sync_water_mark_helper.cpp @@ -301,6 +301,8 @@ DeviceID QuerySyncWaterMarkHelper::GetHashQuerySyncDeviceId(const DeviceID &devi int QuerySyncWaterMarkHelper::GetDeleteSyncWaterMark(const std::string &deviceId, DeleteWaterMark &deleteWaterMark) { std::string hashId = GetHashDeleteSyncDeviceId(deviceId); + // lock prevent different thread visit deleteSyncCache_ + std::lock_guard autoLock(deleteSyncLock_); return GetDeleteWaterMarkFromCache(hashId, deleteWaterMark); } @@ -308,19 +310,22 @@ int QuerySyncWaterMarkHelper::SetSendDeleteSyncWaterMark(const DeviceID &deviceI { std::string hashId = GetHashDeleteSyncDeviceId(deviceId); DeleteWaterMark deleteWaterMark; + // lock prevent different thread visit deleteSyncCache_ + std::lock_guard autoLock(deleteSyncLock_); GetDeleteWaterMarkFromCache(hashId, deleteWaterMark); deleteWaterMark.sendWaterMark = waterMark; - std::lock_guard autoLock(deleteSyncLock_); return UpdateDeleteSyncCacheAndSave(hashId, deleteWaterMark); } -int QuerySyncWaterMarkHelper::SetRecvDeleteSyncWaterMark(const DeviceID &deviceId, const WaterMark &waterMark) +int QuerySyncWaterMarkHelper::SetRecvDeleteSyncWaterMark(const DeviceID &deviceId, const WaterMark &waterMark, + bool isNeedHash) { - std::string hashId = GetHashDeleteSyncDeviceId(deviceId); + std::string hashId = GetHashDeleteSyncDeviceId(deviceId, isNeedHash); DeleteWaterMark deleteWaterMark; + // lock prevent different thread visit deleteSyncCache_ + std::lock_guard autoLock(deleteSyncLock_); GetDeleteWaterMarkFromCache(hashId, deleteWaterMark); deleteWaterMark.recvWaterMark = waterMark; - std::lock_guard autoLock(deleteSyncLock_); return UpdateDeleteSyncCacheAndSave(hashId, deleteWaterMark); } @@ -340,8 +345,6 @@ int QuerySyncWaterMarkHelper::UpdateDeleteSyncCacheAndSave(const std::string &db int QuerySyncWaterMarkHelper::GetDeleteWaterMarkFromCache(const DeviceID &hashDeviceId, DeleteWaterMark &deleteWaterMark) { - // lock prevent different thread visit deleteSyncCache_ - std::lock_guard autoLock(deleteSyncLock_); // if not found if (deleteSyncCache_.find(hashDeviceId) == deleteSyncCache_.end()) { DeleteWaterMark waterMark; @@ -396,12 +399,13 @@ int QuerySyncWaterMarkHelper::SaveDeleteWaterMarkToDB(const DeviceID &hashDevice return errCode; } -DeviceID QuerySyncWaterMarkHelper::GetHashDeleteSyncDeviceId(const DeviceID &deviceId) +DeviceID QuerySyncWaterMarkHelper::GetHashDeleteSyncDeviceId(const DeviceID &deviceId, bool isNeedHash) { DeviceID hashDeleteSyncId; std::lock_guard autoLock(deleteSyncLock_); if (deviceIdToHashDeleteSyncIdMap_.count(deviceId) == 0) { - hashDeleteSyncId = DBConstant::DELETE_SYNC_PREFIX_KEY + DBCommon::TransferHashString(deviceId); + hashDeleteSyncId = DBConstant::DELETE_SYNC_PREFIX_KEY + + (isNeedHash ? DBCommon::TransferHashString(deviceId) : deviceId); deviceIdToHashDeleteSyncIdMap_.insert(std::pair(deviceId, hashDeleteSyncId)); } else { hashDeleteSyncId = deviceIdToHashDeleteSyncIdMap_[deviceId]; @@ -506,11 +510,13 @@ int QuerySyncWaterMarkHelper::RemoveLeastUsedQuerySyncItems(const std::vector autoLock(queryWaterMarkLock_); - std::string prefixKeyStr = DBConstant::QUERY_SYNC_PREFIX_KEY + DBCommon::TransferHashString(deviceId); + std::string prefixKeyStr = DBConstant::QUERY_SYNC_PREFIX_KEY + + (isNeedHash ? DBCommon::TransferHashString(deviceId) : deviceId); if (!tableName.empty()) { std::string hashTableName = DBCommon::TransferHashString(tableName); std::string hexTableName = DBCommon::TransferStringToHex(hashTableName); diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/query_sync_water_mark_helper.h b/kv_store/frameworks/libs/distributeddb/syncer/src/query_sync_water_mark_helper.h index ab36f91e..bb76a503 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/query_sync_water_mark_helper.h +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/query_sync_water_mark_helper.h @@ -66,7 +66,7 @@ public: int SetSendDeleteSyncWaterMark(const std::string &deviceId, const WaterMark &waterMark); - int SetRecvDeleteSyncWaterMark(const std::string &deviceId, const WaterMark &waterMark); + int SetRecvDeleteSyncWaterMark(const std::string &deviceId, const WaterMark &waterMark, bool isNeedHash); // this function will read deleteWaterMark from db by it's deleteWaterMarkKey // and then serialize it and put to cache @@ -76,7 +76,7 @@ public: int RemoveLeastUsedQuerySyncItems(const std::vector &querySyncIds); // reset the waterMark to zero - int ResetRecvQueryWaterMark(const DeviceID &deviceId, const std::string &tableName); + int ResetRecvQueryWaterMark(const DeviceID &deviceId, const std::string &tableName, bool isNeedHash); static std::string GetQuerySyncPrefixKey(); @@ -118,7 +118,7 @@ private: // get the deleteSync hashId in cache_ or generate one and then put it in to cache_ // the hashId is made up of "DELETE_SYNC_PREFIX_KEY" + hash(deviceId) - DeviceID GetHashDeleteSyncDeviceId(const DeviceID &deviceId); + DeviceID GetHashDeleteSyncDeviceId(const DeviceID &deviceId, bool isNeedHash = true); int SaveDeleteWaterMarkToDB(const DeviceID &hashDeviceId, const DeleteWaterMark &deleteWaterMark); diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/remote_executor.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/remote_executor.cpp index aedf9d19..5a72a11d 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/remote_executor.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/remote_executor.cpp @@ -204,12 +204,12 @@ void RemoteExecutor::ParseOneRequestMessage(const std::string &device, Message * } int errCode = CheckPermissions(device); if (errCode != E_OK) { - ResponseFailed(errCode, inMsg->GetSessionId(), inMsg->GetSequenceId(), device); + (void)ResponseFailed(errCode, inMsg->GetSessionId(), inMsg->GetSequenceId(), device); return; } errCode = SendRemoteExecutorData(device, inMsg); if (errCode != E_OK) { - ResponseFailed(errCode, inMsg->GetSessionId(), inMsg->GetSequenceId(), device); + (void)ResponseFailed(errCode, inMsg->GetSessionId(), inMsg->GetSequenceId(), device); } } @@ -507,17 +507,17 @@ int RemoteExecutor::RequestStart(uint32_t sessionId) return errCode; } -void RemoteExecutor::ResponseFailed(int errCode, uint32_t sessionId, uint32_t sequenceId, +int RemoteExecutor::ResponseFailed(int errCode, uint32_t sessionId, uint32_t sequenceId, const std::string &device) { RemoteExecutorAckPacket *packet = new (std::nothrow) RemoteExecutorAckPacket(); if (packet == nullptr) { LOGE("[RemoteExecutor][ResponseFailed] new RemoteExecutorAckPacket error"); - return; + return -E_OUT_OF_MEMORY; } packet->SetAckCode(errCode); packet->SetLastAck(); - (void)ResponseStart(packet, sessionId, sequenceId, device); + return ResponseStart(packet, sessionId, sequenceId, device); } int RemoteExecutor::ResponseData(RelationalRowDataSet &&dataSet, const SendMessage &sendMessage, diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/remote_executor.h b/kv_store/frameworks/libs/distributeddb/syncer/src/remote_executor.h index 68a878d5..f7c1fdd8 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/remote_executor.h +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/remote_executor.h @@ -77,7 +77,7 @@ protected: virtual bool IsPacketValid(uint32_t sessionId); - void ResponseFailed(int errCode, uint32_t sessionId, uint32_t sequenceId, const std::string &device); + int ResponseFailed(int errCode, uint32_t sessionId, uint32_t sequenceId, const std::string &device); private: struct SendMessage { diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/single_ver_data_sync.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/single_ver_data_sync.cpp index c4c3272a..736f7821 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/single_ver_data_sync.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/single_ver_data_sync.cpp @@ -395,6 +395,19 @@ int SingleVerDataSync::SaveData(const SingleVerSyncTaskContext *context, const s if (inData.empty()) { return E_OK; } + StoreInfo info = { + storage_->GetDbProperties().GetStringProp(DBProperties::USER_ID, ""), + storage_->GetDbProperties().GetStringProp(DBProperties::APP_ID, ""), + storage_->GetDbProperties().GetStringProp(DBProperties::STORE_ID, "") + }; + std::string clientId; + int errCode = E_OK; + if (RuntimeContext::GetInstance()->TranslateDeviceId(context->GetDeviceId(), info, clientId) == E_OK) { + errCode = metadata_->SaveClientId(context->GetDeviceId(), clientId); + if (errCode != E_OK) { + LOGW("[DataSync] record clientId failed %d", errCode); + } + } PerformanceAnalysis *performance = PerformanceAnalysis::GetInstance(); if (performance != nullptr) { performance->StepTimeRecordStart(PT_TEST_RECORDS::RECORD_SAVE_DATA); @@ -402,7 +415,6 @@ int SingleVerDataSync::SaveData(const SingleVerSyncTaskContext *context, const s const std::string localHashName = DBCommon::TransferHashString(GetLocalDeviceName()); SingleVerDataSyncUtils::TransSendDataItemToLocal(context, localHashName, inData); - int errCode = E_OK; // query only support prefix key and don't have query in packet in 104 version errCode = storage_->PutSyncDataWithQuery(query, inData, context->GetDeviceId()); if (performance != nullptr) { @@ -1691,6 +1703,10 @@ void SingleVerDataSync::FillRequestReSendPacket(const SingleVerSyncTaskContext * std::vector reserved {reSendInfo.packetId}; packet->SetReserved(reserved); } + if (reSendMode == SyncModeType::PULL) { + // resend pull packet dont set compress type + return; + } bool needCompressOnSync = false; uint8_t compressionRate = DBConstant::DEFAULT_COMPTRESS_RATE; (void)storage_->GetCompressionOption(needCompressOnSync, compressionRate); diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/single_ver_kv_syncer.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/single_ver_kv_syncer.cpp index 4f099ff9..e7541fb5 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/single_ver_kv_syncer.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/single_ver_kv_syncer.cpp @@ -159,29 +159,30 @@ void SingleVerKVSyncer::RemoteDataChanged(const std::string &device) static_cast(syncEngine_)->PutUnfinishedSubQueries(device, syncQueries); } -int SingleVerKVSyncer::SyncConditionCheck(QuerySyncObject &query, int mode, bool isQuerySync, - const std::vector &devices) const +int SingleVerKVSyncer::SyncConditionCheck(const SyncParma ¶m, const ISyncEngine *engine, + ISyncInterface *storage) const { - if (!isQuerySync) { + if (!param.isQuerySync) { return E_OK; } - int errCode = static_cast(syncInterface_)->CheckAndInitQueryCondition(query); + QuerySyncObject query = param.syncQuery; + int errCode = static_cast(storage)->CheckAndInitQueryCondition(query); if (errCode != E_OK) { LOGE("[SingleVerKVSyncer] QuerySyncObject check failed"); return errCode; } - if (mode != SUBSCRIBE_QUERY) { + if (param.mode != SUBSCRIBE_QUERY) { return E_OK; } if (query.HasLimit() || query.HasOrderBy()) { LOGE("[SingleVerKVSyncer] subscribe query not support limit,offset or orderby"); return -E_NOT_SUPPORT; } - if (devices.size() > MAX_DEVICES_NUM) { + if (param.devices.size() > MAX_DEVICES_NUM) { LOGE("[SingleVerKVSyncer] devices is overlimit"); return -E_MAX_LIMITS; } - return syncEngine_->SubscribeLimitCheck(devices, query); + return engine->SubscribeLimitCheck(param.devices, query); } void SingleVerKVSyncer::TriggerSubscribe(const std::string &device, const QuerySyncObject &query) @@ -238,6 +239,17 @@ void SingleVerKVSyncer::TriggerSubQuerySync(const std::vector &devi LOGE("[Syncer] Syncer has not Init"); return; } + std::shared_ptr metadata = nullptr; + ISyncInterface *syncInterface = nullptr; + { + std::lock_guard lock(syncerLock_); + if (metadata_ == nullptr || syncInterface_ == nullptr) { + return; + } + metadata = metadata_; + syncInterface = syncInterface_; + syncInterface->IncRefCount(); + } int errCode; for (auto &device : devices) { std::vector queries; @@ -245,15 +257,8 @@ void SingleVerKVSyncer::TriggerSubQuerySync(const std::vector &devi for (auto &query : queries) { std::string queryId = query.GetIdentify(); WaterMark queryWaterMark = 0; - uint64_t lastTimestamp = 0; - { - std::lock_guard lock(syncerLock_); - if (metadata_ == nullptr) { - return; - } - lastTimestamp = metadata_->GetQueryLastTimestamp(device, queryId); - errCode = metadata_->GetSendQueryWaterMark(queryId, device, queryWaterMark, false); - } + uint64_t lastTimestamp = metadata->GetQueryLastTimestamp(device, queryId); + errCode = metadata->GetSendQueryWaterMark(queryId, device, queryWaterMark, false); if (errCode != E_OK) { LOGE("[Syncer] get queryId=%s,dev=%s watermark failed", STR_MASK(queryId), STR_MASK(device)); continue; @@ -273,6 +278,7 @@ void SingleVerKVSyncer::TriggerSubQuerySync(const std::vector &devi QueryAutoSync(param); } } + syncInterface->DecRefCount(); } SyncerBasicInfo SingleVerKVSyncer::DumpSyncerBasicInfo() diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/single_ver_kv_syncer.h b/kv_store/frameworks/libs/distributeddb/syncer/src/single_ver_kv_syncer.h index 60bf8f58..6ca4a03f 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/single_ver_kv_syncer.h +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/single_ver_kv_syncer.h @@ -38,8 +38,7 @@ public: SyncerBasicInfo DumpSyncerBasicInfo() override; protected: - int SyncConditionCheck(QuerySyncObject &query, int mode, bool isQuerySync, - const std::vector &devices) const override; + int SyncConditionCheck(const SyncParma ¶m, const ISyncEngine *engine, ISyncInterface *storage) const override; private: // if trigger full sync, no need to trigger query sync again diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/single_ver_relational_syncer.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/single_ver_relational_syncer.cpp index 1daf4e20..1b00d4e8 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/single_ver_relational_syncer.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/single_ver_relational_syncer.cpp @@ -167,18 +167,19 @@ void SingleVerRelationalSyncer::SchemaChangeCallback() syncEngine_->SchemaChange(); } -int SingleVerRelationalSyncer::SyncConditionCheck(QuerySyncObject &query, int mode, bool isQuerySync, - const std::vector &devices) const +int SingleVerRelationalSyncer::SyncConditionCheck(const SyncParma ¶m, const ISyncEngine *engine, + ISyncInterface *storage) const { - if (!isQuerySync) { + if (!param.isQuerySync) { return E_OK; } - int errCode = static_cast(syncInterface_)->CheckAndInitQueryCondition(query); + QuerySyncObject query = param.syncQuery; + int errCode = static_cast(storage)->CheckAndInitQueryCondition(query); if (errCode != E_OK) { LOGE("[SingleVerRelationalSyncer] QuerySyncObject check failed"); return errCode; } - if (mode == SUBSCRIBE_QUERY) { + if (param.mode == SUBSCRIBE_QUERY) { return -E_NOT_SUPPORT; } return E_OK; diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/single_ver_relational_syncer.h b/kv_store/frameworks/libs/distributeddb/syncer/src/single_ver_relational_syncer.h index 8a733a06..04102c8d 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/single_ver_relational_syncer.h +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/single_ver_relational_syncer.h @@ -35,8 +35,7 @@ protected: int PrepareSync(const SyncParma ¶m, uint32_t syncId, uint64_t connectionId) override; - int SyncConditionCheck(QuerySyncObject &query, int mode, bool isQuerySync, - const std::vector &devices) const override; + int SyncConditionCheck(const SyncParma ¶m, const ISyncEngine *engine, ISyncInterface *storage) const override; private: diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/single_ver_serialize_manager.h b/kv_store/frameworks/libs/distributeddb/syncer/src/single_ver_serialize_manager.h index cb4035b1..33f19fc7 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/single_ver_serialize_manager.h +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/single_ver_serialize_manager.h @@ -16,6 +16,7 @@ #ifndef SINGLE_VER_SERIALIZE_MANAGER_NEW_H #define SINGLE_VER_SERIALIZE_MANAGER_NEW_H +#include #include "icommunicator.h" #include "isync_packet.h" #include "message_transform.h" diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/single_ver_sync_task_context.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/single_ver_sync_task_context.cpp index 278ff798..aa753b1d 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/single_ver_sync_task_context.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/single_ver_sync_task_context.cpp @@ -490,6 +490,7 @@ void SingleVerSyncTaskContext::SaveLastPushTaskExecStatus(int finalStatus) if (mode_ == SyncModeType::PUSH || mode_ == SyncModeType::PUSH_AND_PULL || mode_ == SyncModeType::RESPONSE_PULL) { lastFullSyncTaskStatus_ = finalStatus; } else if (mode_ == SyncModeType::QUERY_PUSH || mode_ == SyncModeType::QUERY_PUSH_PULL) { + std::lock_guard autoLock(queryTaskStatusMutex_); lastQuerySyncTaskStatusMap_[syncOperation_->GetQueryId()] = finalStatus; } } @@ -515,6 +516,7 @@ int SingleVerSyncTaskContext::GetCorrectedSendWaterMarkForCurrentTask(const Sync void SingleVerSyncTaskContext::ResetLastPushTaskStatus() { lastFullSyncTaskStatus_ = SyncOperation::OP_WAITING; + std::lock_guard autoLock(queryTaskStatusMutex_); lastQuerySyncTaskStatusMap_.clear(); } @@ -536,6 +538,7 @@ bool SingleVerSyncTaskContext::IsCurrentSyncTaskCanBeSkippedInner(const SyncOper if (operation == nullptr) { return true; } + std::lock_guard autoLock(queryTaskStatusMutex_); auto it = lastQuerySyncTaskStatusMap_.find(operation->GetQueryId()); if (it == lastQuerySyncTaskStatusMap_.end()) { // no last query_push and push diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/single_ver_sync_task_context.h b/kv_store/frameworks/libs/distributeddb/syncer/src/single_ver_sync_task_context.h index 4aff0679..19145a8b 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/single_ver_sync_task_context.h +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/single_ver_sync_task_context.h @@ -145,7 +145,7 @@ protected: bool isQuerySync_ = false; // for merge sync task - int lastFullSyncTaskStatus_ = SyncOperation::Status::OP_WAITING; + volatile int lastFullSyncTaskStatus_ = SyncOperation::Status::OP_WAITING; private: int GetCorrectedSendWaterMarkForCurrentTask(const SyncOperation *operation, uint64_t &waterMark) const; @@ -172,6 +172,7 @@ private: // For subscribe manager std::shared_ptr subManager_; + mutable std::mutex queryTaskStatusMutex_; // std::unordered_map lastQuerySyncTaskStatusMap_; }; diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/single_ver_syncer.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/single_ver_syncer.cpp index fd754fb4..0e422349 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/single_ver_syncer.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/single_ver_syncer.cpp @@ -92,4 +92,17 @@ ISyncEngine *SingleVerSyncer::CreateSyncEngine() { return new (std::nothrow) SingleVerSyncEngine(); } + +int SingleVerSyncer::GetHashDeviceId(const std::string &clientId, std::string &hashDevId) +{ + std::shared_ptr metadata = nullptr; + { + std::lock_guard lock(syncerLock_); + if (metadata_ == nullptr) { + return -E_NOT_INIT; + } + metadata = metadata_; + } + return metadata->GetHashDeviceId(clientId, hashDevId); +} } diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/single_ver_syncer.h b/kv_store/frameworks/libs/distributeddb/syncer/src/single_ver_syncer.h index 9dc5e0e1..e352b2ad 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/single_ver_syncer.h +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/single_ver_syncer.h @@ -34,6 +34,7 @@ public: int EraseDeviceWaterMark(const std::string &deviceId, bool isNeedHash, const std::string &tableName) override; + int GetHashDeviceId(const std::string &clientId, std::string &hashDevId) override; protected: // Create a sync engine, if has memory error, will return nullptr. ISyncEngine *CreateSyncEngine() override; diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/sync_engine.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/sync_engine.cpp index 61733a69..938fcacf 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/sync_engine.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/sync_engine.cpp @@ -661,36 +661,39 @@ int SyncEngine::ExecSyncTask(ISyncTaskContext *context) if (IsKilled()) { return -E_OBJ_IS_KILLED; } - AutoLock lockGuard(context); int status = context->GetTaskExecStatus(); if ((status == SyncTaskContext::RUNNING) || context->IsKilled()) { return -E_NOT_SUPPORT; } context->SetTaskExecStatus(ISyncTaskContext::RUNNING); - if (!context->IsTargetQueueEmpty()) { - int errCode = context->GetNextTarget(true); + while (!context->IsTargetQueueEmpty()) { + int errCode = context->GetNextTarget(); if (errCode != E_OK) { - return errCode; + // current task execute failed, try next task + context->ClearSyncOperation(); + continue; } if (context->IsCurrentSyncTaskCanBeSkipped()) { context->SetOperationStatus(SyncOperation::OP_FINISHED_ALL); context->ClearSyncOperation(); - context->SetTaskExecStatus(ISyncTaskContext::FINISHED); - return E_OK; + continue; } context->UnlockObj(); errCode = context->StartStateMachine(); context->LockObj(); if (errCode != E_OK) { - LOGE("[SyncEngine] machine StartSync failed"); + // machine start failed because timer start failed, try to execute next task + LOGW("[SyncEngine] machine StartSync failed"); context->SetOperationStatus(SyncOperation::OP_FAILED); - return errCode; + context->ClearSyncOperation(); + continue; } - } else { - LOGD("[SyncEngine] ExecSyncTask finished"); - context->SetTaskExecStatus(ISyncTaskContext::FINISHED); + // now task is running just return here + return errCode; } + LOGD("[SyncEngine] ExecSyncTask finished"); + context->SetTaskExecStatus(ISyncTaskContext::FINISHED); return E_OK; } diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/sync_state_machine.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/sync_state_machine.cpp index 9115edd0..374ce915 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/sync_state_machine.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/sync_state_machine.cpp @@ -174,18 +174,21 @@ int SyncStateMachine::ExecNextTask() { syncContext_->Clear(); while (!syncContext_->IsTargetQueueEmpty()) { - int errCode = syncContext_->GetNextTarget(false); + int errCode = syncContext_->GetNextTarget(); if (errCode != E_OK) { continue; } if (syncContext_->IsCurrentSyncTaskCanBeSkipped()) { syncContext_->SetOperationStatus(SyncOperation::OP_FINISHED_ALL); + syncContext_->Clear(); continue; } errCode = PrepareNextSyncTask(); if (errCode != E_OK) { LOGE("[SyncStateMachine] PrepareSync failed"); syncContext_->SetOperationStatus(SyncOperation::OP_FAILED); + syncContext_->Clear(); + continue; // try to execute next task } return errCode; } diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/sync_task_context.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/sync_task_context.cpp index 97499394..a615c38d 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/sync_task_context.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/sync_task_context.cpp @@ -89,13 +89,20 @@ int SyncTaskContext::AddSyncTarget(ISyncTarget *target) return -E_INVALID_ARGS; } } - CancelCurrentSyncRetryIfNeed(targetMode); + RefObject::IncObjRef(this); + int errCode = RuntimeContext::GetInstance()->ScheduleTask([this, targetMode]() { + CancelCurrentSyncRetryIfNeed(targetMode); + RefObject::DecObjRef(this); + }); + if (errCode != E_OK) { + RefObject::DecObjRef(this); + } if (taskExecStatus_ == RUNNING) { return E_OK; } if (onSyncTaskAdd_) { RefObject::IncObjRef(this); - int errCode = RuntimeContext::GetInstance()->ScheduleTask([this]() { + errCode = RuntimeContext::GetInstance()->ScheduleTask([this]() { onSyncTaskAdd_(); RefObject::DecObjRef(this); }); @@ -260,15 +267,12 @@ void SyncTaskContext::MoveToNextTarget() } } -int SyncTaskContext::GetNextTarget(bool isNeedSetFinished) +int SyncTaskContext::GetNextTarget() { MoveToNextTarget(); int checkErrCode = RunPermissionCheck(GetPermissionCheckFlag(IsAutoSync(), GetMode())); if (checkErrCode != E_OK) { SetOperationStatus(SyncOperation::OP_PERMISSION_CHECK_FAILED); - if (isNeedSetFinished) { - SetTaskExecStatus(ISyncTaskContext::FINISHED); - } return checkErrCode; } return E_OK; diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/sync_task_context.h b/kv_store/frameworks/libs/distributeddb/syncer/src/sync_task_context.h index 1eb06538..8ecf2837 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/sync_task_context.h +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/sync_task_context.h @@ -70,7 +70,7 @@ public: // Move to next target to sync void MoveToNextTarget() override; - int GetNextTarget(bool isNeedSetFinished) override; + int GetNextTarget() override; // Get the current task syncId uint32_t GetSyncId() const override; diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/syncer_proxy.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/syncer_proxy.cpp index 324b4ea0..6d55a01b 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/syncer_proxy.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/syncer_proxy.cpp @@ -231,4 +231,12 @@ int SyncerProxy::GetSyncDataSize(const std::string &device, size_t &size) const } return syncer_->GetSyncDataSize(device, size); } + +int SyncerProxy::GetHashDeviceId(const std::string &clientId, std::string &hashDevId) +{ + if (syncer_ == nullptr) { + return -E_NOT_INIT; + } + return syncer_->GetHashDeviceId(clientId, hashDevId); +} } // namespace DistributedDB diff --git a/kv_store/frameworks/libs/distributeddb/test/BUILD.gn b/kv_store/frameworks/libs/distributeddb/test/BUILD.gn index e812b2ab..8b8a3713 100644 --- a/kv_store/frameworks/libs/distributeddb/test/BUILD.gn +++ b/kv_store/frameworks/libs/distributeddb/test/BUILD.gn @@ -63,6 +63,7 @@ config("module_private_config") { "USE_DFX_ABILITY", "TRACE_SQLITE_EXECUTE", "SQLITE_ENABLE_DROPTABLE_CALLBACK", + "OPENSSL_SUPPRESS_DEPRECATED", ] } @@ -201,6 +202,7 @@ ohos_source_set("src_file") { "../storage/src/sqlite/sqlite_local_storage_engine.cpp", "../storage/src/sqlite/sqlite_local_storage_executor.cpp", "../storage/src/sqlite/sqlite_log_table_manager.cpp", + "../storage/src/sqlite/sqlite_meta_executor.cpp", "../storage/src/sqlite/sqlite_multi_ver_data_storage.cpp", "../storage/src/sqlite/sqlite_multi_ver_transaction.cpp", "../storage/src/sqlite/sqlite_query_helper.cpp", diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/delegate_fuzzer/BUILD.gn b/kv_store/frameworks/libs/distributeddb/test/fuzztest/delegate_fuzzer/BUILD.gn index 14a11bbf..efed0f98 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/delegate_fuzzer/BUILD.gn +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/delegate_fuzzer/BUILD.gn @@ -84,6 +84,7 @@ ohos_fuzztest("DelegateFuzzTest") { "RELATIONAL_STORE", "SQLITE_DISTRIBUTE_RELATIONAL", "SQLITE_ENABLE_DROPTABLE_CALLBACK", + "OPENSSL_SUPPRESS_DEPRECATED", ] deps = [ diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/delegate_fuzzer/delegate_fuzzer.cpp b/kv_store/frameworks/libs/distributeddb/test/fuzztest/delegate_fuzzer/delegate_fuzzer.cpp index fb3a4cb7..c2e20ea2 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/delegate_fuzzer/delegate_fuzzer.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/delegate_fuzzer/delegate_fuzzer.cpp @@ -36,21 +36,29 @@ std::vector CreateEntries(const uint8_t* data, size_t size, std::vectorUnRegisterObserver(observer); + delete observer; return; } auto valueCallback = [&value] (DBStatus status, const Value &getValue) { @@ -82,9 +92,10 @@ void MultiCombineFuzzer(const uint8_t* data, size_t size, KvStoreDelegate::Optio kvDelegatePtr->DeleteBatch(keys); kvDelegatePtr->Clear(); kvDelegatePtr->UnRegisterObserver(observer); + delete observer; kvDelegatePtr->ReleaseKvStoreSnapshot(kvStoreSnapshotPtr); - kvManger.CloseKvStore(kvDelegatePtr); - kvManger.DeleteKvStore("distributed_delegate_test"); + g_kvManger.CloseKvStore(kvDelegatePtr); + g_kvManger.DeleteKvStore("distributed_delegate_test"); DistributedDBToolsTest::RemoveTestDbFiles(config.dataDir); } } diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/fileoper_fuzzer/BUILD.gn b/kv_store/frameworks/libs/distributeddb/test/fuzztest/fileoper_fuzzer/BUILD.gn index a73111fc..825390ba 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/fileoper_fuzzer/BUILD.gn +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/fileoper_fuzzer/BUILD.gn @@ -93,6 +93,7 @@ ohos_fuzztest("FileOperFuzzTest") { "RELATIONAL_STORE", "SQLITE_DISTRIBUTE_RELATIONAL", "SQLITE_ENABLE_DROPTABLE_CALLBACK", + "OPENSSL_SUPPRESS_DEPRECATED", ] external_deps = [ diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/importfile_fuzzer/BUILD.gn b/kv_store/frameworks/libs/distributeddb/test/fuzztest/importfile_fuzzer/BUILD.gn index 15f738c1..2d60cdfa 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/importfile_fuzzer/BUILD.gn +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/importfile_fuzzer/BUILD.gn @@ -85,6 +85,7 @@ ohos_fuzztest("ImportFileFuzzTest") { "RELATIONAL_STORE", "SQLITE_DISTRIBUTE_RELATIONAL", "SQLITE_ENABLE_DROPTABLE_CALLBACK", + "OPENSSL_SUPPRESS_DEPRECATED", ] deps = [ diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/iprocesscommunicator_fuzzer/BUILD.gn b/kv_store/frameworks/libs/distributeddb/test/fuzztest/iprocesscommunicator_fuzzer/BUILD.gn index a6a320ab..3fde0643 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/iprocesscommunicator_fuzzer/BUILD.gn +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/iprocesscommunicator_fuzzer/BUILD.gn @@ -84,6 +84,7 @@ ohos_fuzztest("IProcessCommunicatorFuzzTest") { "RELATIONAL_STORE", "SQLITE_DISTRIBUTE_RELATIONAL", "SQLITE_ENABLE_DROPTABLE_CALLBACK", + "OPENSSL_SUPPRESS_DEPRECATED", ] deps = [ diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/kvdelegatemanager_fuzzer/BUILD.gn b/kv_store/frameworks/libs/distributeddb/test/fuzztest/kvdelegatemanager_fuzzer/BUILD.gn index 2ff25d9b..739b6f51 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/kvdelegatemanager_fuzzer/BUILD.gn +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/kvdelegatemanager_fuzzer/BUILD.gn @@ -85,6 +85,7 @@ ohos_fuzztest("KvDelegateManagerFuzzTest") { "RELATIONAL_STORE", "SQLITE_DISTRIBUTE_RELATIONAL", "SQLITE_ENABLE_DROPTABLE_CALLBACK", + "OPENSSL_SUPPRESS_DEPRECATED", ] deps = [ diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/kvstoreresultset_fuzzer/BUILD.gn b/kv_store/frameworks/libs/distributeddb/test/fuzztest/kvstoreresultset_fuzzer/BUILD.gn index 52d66d87..64023811 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/kvstoreresultset_fuzzer/BUILD.gn +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/kvstoreresultset_fuzzer/BUILD.gn @@ -85,6 +85,7 @@ ohos_fuzztest("KvStoreResultSetFuzzTest") { "RELATIONAL_STORE", "SQLITE_DISTRIBUTE_RELATIONAL", "SQLITE_ENABLE_DROPTABLE_CALLBACK", + "OPENSSL_SUPPRESS_DEPRECATED", ] deps = [ diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/nbdelegate_fuzzer/BUILD.gn b/kv_store/frameworks/libs/distributeddb/test/fuzztest/nbdelegate_fuzzer/BUILD.gn index aa1dca95..0741d160 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/nbdelegate_fuzzer/BUILD.gn +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/nbdelegate_fuzzer/BUILD.gn @@ -84,6 +84,7 @@ ohos_fuzztest("NbDelegateFuzzTest") { "RELATIONAL_STORE", "SQLITE_DISTRIBUTE_RELATIONAL", "SQLITE_ENABLE_DROPTABLE_CALLBACK", + "OPENSSL_SUPPRESS_DEPRECATED", ] deps = [ diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/nbdelegate_fuzzer/nbdelegate_fuzzer.cpp b/kv_store/frameworks/libs/distributeddb/test/fuzztest/nbdelegate_fuzzer/nbdelegate_fuzzer.cpp index 983271bd..0766f5e9 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/nbdelegate_fuzzer/nbdelegate_fuzzer.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/nbdelegate_fuzzer/nbdelegate_fuzzer.cpp @@ -144,6 +144,24 @@ void FuzzSetInterceptorTest(KvStoreNbDelegate *kvNbDelegatePtr) ); } +void TestCRUD(const Key &key, const Value &value, KvStoreNbDelegate *kvNbDelegatePtr) +{ + Value valueRead; + kvNbDelegatePtr->PutLocal(key, value); + kvNbDelegatePtr->GetLocal(key, valueRead); + kvNbDelegatePtr->DeleteLocal(key); + kvNbDelegatePtr->Put(key, value); + kvNbDelegatePtr->Put(key, value); + kvNbDelegatePtr->UpdateKey([](const Key &origin, Key &newKey) { + newKey = origin; + newKey.push_back('0'); + }); + std::vector vect; + kvNbDelegatePtr->GetEntries(key, vect); + kvNbDelegatePtr->Delete(key); + kvNbDelegatePtr->Get(key, valueRead); +} + void FuzzCURD(const uint8_t* data, size_t size, KvStoreNbDelegate *kvNbDelegatePtr) { auto observer = new (std::nothrow) KvStoreObserverFuzzTest; @@ -156,17 +174,7 @@ void FuzzCURD(const uint8_t* data, size_t size, KvStoreNbDelegate *kvNbDelegateP kvNbDelegatePtr->SetConflictNotifier(size, [](const KvStoreNbConflictData &data) { (void)data.GetType(); }); - - Value valueRead; - kvNbDelegatePtr->PutLocal(key, value); - kvNbDelegatePtr->GetLocal(key, valueRead); - kvNbDelegatePtr->DeleteLocal(key); - kvNbDelegatePtr->Put(key, value); - kvNbDelegatePtr->Put(key, value); - std::vector vect; - kvNbDelegatePtr->GetEntries(key, vect); - kvNbDelegatePtr->Delete(key); - kvNbDelegatePtr->Get(key, valueRead); + TestCRUD(key, value, kvNbDelegatePtr); std::vector keys; std::vector tmp = CreateEntries(data, size, keys); kvNbDelegatePtr->PutBatch(tmp); @@ -178,6 +186,8 @@ void FuzzCURD(const uint8_t* data, size_t size, KvStoreNbDelegate *kvNbDelegateP } kvNbDelegatePtr->DeleteBatch(keys); kvNbDelegatePtr->UnRegisterObserver(observer); + delete observer; + observer = nullptr; kvNbDelegatePtr->PutLocalBatch(tmp); kvNbDelegatePtr->DeleteLocalBatch(keys); std::string tmpStoreId = kvNbDelegatePtr->GetStoreId(); diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/parseckeck_fuzzer/BUILD.gn b/kv_store/frameworks/libs/distributeddb/test/fuzztest/parseckeck_fuzzer/BUILD.gn index b2eb988b..403c683d 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/parseckeck_fuzzer/BUILD.gn +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/parseckeck_fuzzer/BUILD.gn @@ -85,6 +85,7 @@ ohos_fuzztest("ParseCkeckFuzzTest") { "RELATIONAL_STORE", "SQLITE_DISTRIBUTE_RELATIONAL", "SQLITE_ENABLE_DROPTABLE_CALLBACK", + "OPENSSL_SUPPRESS_DEPRECATED", ] deps = [ diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/query_fuzzer/BUILD.gn b/kv_store/frameworks/libs/distributeddb/test/fuzztest/query_fuzzer/BUILD.gn index f8063cfe..27e317f3 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/query_fuzzer/BUILD.gn +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/query_fuzzer/BUILD.gn @@ -83,6 +83,7 @@ ohos_fuzztest("QueryFuzzTest") { "RELATIONAL_STORE", "SQLITE_DISTRIBUTE_RELATIONAL", "SQLITE_ENABLE_DROPTABLE_CALLBACK", + "OPENSSL_SUPPRESS_DEPRECATED", ] deps = [ diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/rekey_fuzzer/BUILD.gn b/kv_store/frameworks/libs/distributeddb/test/fuzztest/rekey_fuzzer/BUILD.gn index 2c77f077..d70da426 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/rekey_fuzzer/BUILD.gn +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/rekey_fuzzer/BUILD.gn @@ -85,6 +85,7 @@ ohos_fuzztest("ReKeyFuzzTest") { "RELATIONAL_STORE", "SQLITE_DISTRIBUTE_RELATIONAL", "SQLITE_ENABLE_DROPTABLE_CALLBACK", + "OPENSSL_SUPPRESS_DEPRECATED", ] deps = [ diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/relationalstoredelegate_fuzzer/BUILD.gn b/kv_store/frameworks/libs/distributeddb/test/fuzztest/relationalstoredelegate_fuzzer/BUILD.gn index 72df4d36..c3f7947e 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/relationalstoredelegate_fuzzer/BUILD.gn +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/relationalstoredelegate_fuzzer/BUILD.gn @@ -90,6 +90,7 @@ ohos_fuzztest("RelationalstoredelegateFuzzTest") { "SQLITE_DISTRIBUTE_RELATIONAL", "SQLITE_EXPORT_SYMBOLS", "SQLITE_ENABLE_DROPTABLE_CALLBACK", + "OPENSSL_SUPPRESS_DEPRECATED", ] deps = [ diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/relationalstoredelegate_fuzzer/relationalstoredelegate_fuzzer.cpp b/kv_store/frameworks/libs/distributeddb/test/fuzztest/relationalstoredelegate_fuzzer/relationalstoredelegate_fuzzer.cpp index 9a3e1ecb..2cf32a8a 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/relationalstoredelegate_fuzzer/relationalstoredelegate_fuzzer.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/relationalstoredelegate_fuzzer/relationalstoredelegate_fuzzer.cpp @@ -23,7 +23,7 @@ #include "virtual_communicator_aggregator.h" #include "query.h" #include "store_types.h" -#include "result_set.h" +#include "distributeddb/result_set.h" #include "runtime_context.h" namespace OHOS { @@ -118,6 +118,7 @@ void CombineTest(const uint8_t* data, size_t size) } g_delegate->Sync(device, mode, query, nullptr, len % 2); // 2 is mod num for wait parameter std::string deviceId = device.size() > 0 ? device[0] : tableName; + g_delegate->RemoveDeviceData(); g_delegate->RemoveDeviceData(deviceId); g_delegate->RemoveDeviceData(deviceId, tableName); diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/relationalstoremanager_fuzzer/BUILD.gn b/kv_store/frameworks/libs/distributeddb/test/fuzztest/relationalstoremanager_fuzzer/BUILD.gn index dbd859f2..652223af 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/relationalstoremanager_fuzzer/BUILD.gn +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/relationalstoremanager_fuzzer/BUILD.gn @@ -89,6 +89,7 @@ ohos_fuzztest("RelationalstoremanagerFuzzTest") { "SQLITE_DISTRIBUTE_RELATIONAL", "SQLITE_EXPORT_SYMBOLS", "SQLITE_ENABLE_DROPTABLE_CALLBACK", + "OPENSSL_SUPPRESS_DEPRECATED", ] deps = [ diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/relationalstoremanager_fuzzer/relationalstoremanager_fuzzer.cpp b/kv_store/frameworks/libs/distributeddb/test/fuzztest/relationalstoremanager_fuzzer/relationalstoremanager_fuzzer.cpp index 56215351..c5fd1f9c 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/relationalstoremanager_fuzzer/relationalstoremanager_fuzzer.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/relationalstoremanager_fuzzer/relationalstoremanager_fuzzer.cpp @@ -79,6 +79,9 @@ void CombineTest(const uint8_t* data, size_t size) g_mgr.OpenStore(g_dbDir + appId + DB_SUFFIX, storeId, {}, g_delegate); g_mgr.GetRelationalStoreIdentifier(userId, appId, storeId, instanceId % 2); // 2 is mod num for last parameter RuntimeConfig::SetProcessLabel(appId, userId); + RuntimeConfig::SetTranslateToDeviceIdCallback([](const std::string &oriDevId, const StoreInfo &info) { + return oriDevId + "_" + info.appId; + }); } } diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/schemadelegate_fuzzer/BUILD.gn b/kv_store/frameworks/libs/distributeddb/test/fuzztest/schemadelegate_fuzzer/BUILD.gn index 8243f00a..2b82a09c 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/schemadelegate_fuzzer/BUILD.gn +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/schemadelegate_fuzzer/BUILD.gn @@ -84,6 +84,7 @@ ohos_fuzztest("SchemaDelegateFuzzTest") { "RELATIONAL_STORE", "SQLITE_DISTRIBUTE_RELATIONAL", "SQLITE_ENABLE_DROPTABLE_CALLBACK", + "OPENSSL_SUPPRESS_DEPRECATED", ] deps = [ diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/sync_fuzzer/BUILD.gn b/kv_store/frameworks/libs/distributeddb/test/fuzztest/sync_fuzzer/BUILD.gn index 89b451be..197221a8 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/sync_fuzzer/BUILD.gn +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/sync_fuzzer/BUILD.gn @@ -90,6 +90,7 @@ ohos_fuzztest("SyncFuzzTest") { "RELATIONAL_STORE", "SQLITE_DISTRIBUTE_RELATIONAL", "SQLITE_ENABLE_DROPTABLE_CALLBACK", + "OPENSSL_SUPPRESS_DEPRECATED", ] deps = [ diff --git a/kv_store/frameworks/libs/distributeddb/test/moduletest/BUILD.gn b/kv_store/frameworks/libs/distributeddb/test/moduletest/BUILD.gn index eeb51b20..d16cccf7 100644 --- a/kv_store/frameworks/libs/distributeddb/test/moduletest/BUILD.gn +++ b/kv_store/frameworks/libs/distributeddb/test/moduletest/BUILD.gn @@ -59,6 +59,7 @@ config("module_private_config") { "RELEASE_MODE_V2", "RELEASE_MODE_V3", "OMIT_MULTI_VER", + "OPENSSL_SUPPRESS_DEPRECATED", ] ldflags = [ "-Wl,--exclude-libs,ALL" ] } diff --git a/kv_store/frameworks/libs/distributeddb/test/moduletest/src/distributeddb_kv_crud_test.cpp b/kv_store/frameworks/libs/distributeddb/test/moduletest/src/distributeddb_kv_crud_test.cpp index b9ee63b1..9623e823 100644 --- a/kv_store/frameworks/libs/distributeddb/test/moduletest/src/distributeddb_kv_crud_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/moduletest/src/distributeddb_kv_crud_test.cpp @@ -651,21 +651,6 @@ HWTEST_F(DistributeddbKvCrudTest, ComplexDataTest006, TestSize.Level1) EXPECT_TRUE(valueResult.size() == 0); } -/* - * @tc.name: ComplexDataTest 007 - * @tc.desc: Verify that can operate chinese string key and value. - * @tc.type: FUNC - * @tc.require: SR000BUH3J - * @tc.author: luqianfu - */ -HWTEST_F(DistributeddbKvCrudTest, ComplexDataTest007, TestSize.Level1) -{ - /* - * @tc.steps: step1. create kv db and put(k,OK_VALUE_1) that k="中文"and get. - * @tc.expected: step1. put successfully and get the value of k is OK_VALUE_1. - */ -} - /* * @tc.name: ReadWritePerformance 001 * @tc.desc: calculate the time of put-get in 16b-100b/16b-100kb, 1k times' random-put&get. @@ -710,12 +695,12 @@ HWTEST_F(DistributeddbKvCrudTest, ReadWritePerformance001, TestSize.Level3) }; for (int ps = 0; ps < PERFORMANCE_SIZE; ++ps) { - DistributedTestTools::CalculateOpenPerformance(performanceData[ps]); - DistributedTestTools::CalculateInsertPerformance(performanceData[ps]); - DistributedTestTools::CalculateGetPutPerformance(performanceData[ps]); - DistributedTestTools::CalculateUpdatePerformance(performanceData[ps]); - DistributedTestTools::CalculateGetUpdatePerformance(performanceData[ps]); - DistributedTestTools::CalculateUseClearPerformance(performanceData[ps]); + EXPECT_TRUE(DistributedTestTools::CalculateOpenPerformance(performanceData[ps])); + EXPECT_TRUE(DistributedTestTools::CalculateInsertPerformance(performanceData[ps])); + EXPECT_TRUE(DistributedTestTools::CalculateGetPutPerformance(performanceData[ps])); + EXPECT_TRUE(DistributedTestTools::CalculateUpdatePerformance(performanceData[ps])); + EXPECT_TRUE(DistributedTestTools::CalculateGetUpdatePerformance(performanceData[ps])); + EXPECT_TRUE(DistributedTestTools::CalculateUseClearPerformance(performanceData[ps])); } } } diff --git a/kv_store/frameworks/libs/distributeddb/test/moduletest/src/distributeddb_nb_create_test.cpp b/kv_store/frameworks/libs/distributeddb/test/moduletest/src/distributeddb_nb_create_test.cpp index ed024c7c..649dc9f5 100644 --- a/kv_store/frameworks/libs/distributeddb/test/moduletest/src/distributeddb_nb_create_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/moduletest/src/distributeddb_nb_create_test.cpp @@ -71,27 +71,6 @@ void DistributeddbNbCreateTest::TearDown(void) { } -void WaitingDeletingDB() -{ - KvStoreDelegateManager *manager = nullptr; - KvStoreNbDelegate *result = nullptr; - /** - * @tc.steps: step2. delete db when kill the process manually. - * @tc.expected: step2. delete success. - */ - result = DistributedDBNbTestTools::GetNbDelegateSuccess(manager, g_dbParameter2, g_option); - ASSERT_TRUE(manager != nullptr && result != nullptr); - EXPECT_EQ(manager->CloseKvStore(result), OK); - result = nullptr; - if (!g_option.isMemoryDb) { - EXPECT_EQ(manager->DeleteKvStore(STORE_ID_2), OK); - } - MST_LOG("please kill the testing process..."); - std::this_thread::sleep_for(std::chrono::seconds(TWENTY_SECONDS)); - delete manager; - manager = nullptr; -} - /* * @tc.name: ManagerDb 001 * @tc.desc: Verify that can create distributed db normally. @@ -986,24 +965,6 @@ HWTEST_F(DistributeddbNbCreateTest, ManagerDb029, TestSize.Level0) manager = nullptr; } -/* - * @tc.name: ManagerDb 030 - * @tc.desc: verify that can delete the db success even if the deleting process is killed when it is deleting the db. - * @tc.type: FUNC - * @tc.require: SR000CCPOI - * @tc.author: luqianfu - */ -HWTEST_F(DistributeddbNbCreateTest, ManagerDb030, TestSize.Level2) -{ - /** - * @tc.steps: step1. start thread. - * @tc.expected: step1. success. - */ - std::thread th(WaitingDeletingDB); - th.detach(); - std::this_thread::sleep_for(std::chrono::seconds(UNIQUE_SECOND)); -} - /* * @tc.name: MemoryDb 001 * @tc.desc: verify that can create memory db successfully. diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/communicator/distributeddb_communicator_deep_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/communicator/distributeddb_communicator_deep_test.cpp index e5a96775..652b9414 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/communicator/distributeddb_communicator_deep_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/communicator/distributeddb_communicator_deep_test.cpp @@ -146,11 +146,16 @@ HWTEST_F(DistributedDBCommunicatorDeepTest, WaitAndRetrySend001, TestSize.Level2 g_commBB->RegOnMessageCallback([&msgForBB](const std::string &srcTarget, Message *inMsg) { msgForBB = inMsg; }, nullptr); + Message *msgForCA = nullptr; + g_commCA->RegOnMessageCallback([&msgForCA](const std::string &srcTarget, Message *inMsg) { + msgForCA = inMsg; + }, nullptr); /** * @tc.steps: step1. connect device A with device B */ AdapterStub::ConnectAdapterStub(g_envDeviceA.adapterHandle, g_envDeviceB.adapterHandle); + AdapterStub::ConnectAdapterStub(g_envDeviceA.adapterHandle, g_envDeviceC.adapterHandle); std::this_thread::sleep_for(std::chrono::milliseconds(200)); // Wait 200 ms to make sure quiet /** @@ -167,8 +172,16 @@ HWTEST_F(DistributedDBCommunicatorDeepTest, WaitAndRetrySend001, TestSize.Level2 SendConfig conf = {true, false, 0}; int errCode = g_commAB->SendMessage(DEVICE_NAME_B, msgForAB, conf); EXPECT_EQ(errCode, E_OK); + + Message *msgForAA = BuildRegedTinyMessage(); + ASSERT_NE(msgForAA, nullptr); + errCode = g_commAA->SendMessage(DEVICE_NAME_C, msgForAA, conf); + EXPECT_EQ(errCode, E_OK); std::this_thread::sleep_for(std::chrono::milliseconds(100)); // Wait 100 ms EXPECT_EQ(msgForBB, nullptr); + EXPECT_NE(msgForCA, nullptr); + delete msgForCA; + msgForCA = nullptr; /** * @tc.steps: step4. device A simulate sendable feedback diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_database_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_database_test.cpp index c8a083ca..62b665f3 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_database_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_database_test.cpp @@ -1303,6 +1303,35 @@ namespace { } LOGD("Succeed %d times", totalNum); } + + void FreqOpenClose001() + { + std::string storeId = "FrqOpenClose001"; + std::thread t1(OpenCloseDatabase, storeId); + std::thread t2(OpenCloseDatabase, storeId); + std::thread t3(OpenCloseDatabase, storeId); + std::thread t4(OpenCloseDatabase, storeId); + t1.join(); + t2.join(); + t3.join(); + t4.join(); + EXPECT_EQ(g_mgr.DeleteKvStore(storeId), OK); + } + + void FreqOpenCloseDel001() + { + std::string storeId = "FrqOpenCloseDelete001"; + std::thread t1(OpenCloseDatabase, storeId); + std::thread t2([&]() { + for (int i = 0; i < 10000; i++) { // loop 10000 times + DBStatus status = g_mgr.DeleteKvStore(storeId); + LOGI("delete res %d", status); + EXPECT_TRUE(status == OK || status == BUSY || status == NOT_FOUND); + } + }); + t1.join(); + t2.join(); + } } /** @@ -1314,15 +1343,7 @@ namespace { */ HWTEST_F(DistributedDBInterfacesDatabaseTest, FreqOpenCloseDel001, TestSize.Level2) { - std::string storeId = "FrqOpenCloseDelete001"; - std::thread t1(OpenCloseDatabase, storeId); - std::thread t2([&]() { - for (int i = 0; i < 10000; i++) { - g_mgr.DeleteKvStore(storeId); - } - }); - t1.join(); - t2.join(); + ASSERT_NO_FATAL_FAILURE(FreqOpenCloseDel001()); } /** @@ -1334,16 +1355,7 @@ HWTEST_F(DistributedDBInterfacesDatabaseTest, FreqOpenCloseDel001, TestSize.Leve */ HWTEST_F(DistributedDBInterfacesDatabaseTest, FreqOpenClose001, TestSize.Level2) { - std::string storeId = "FrqOpenClose001"; - std::thread t1(OpenCloseDatabase, storeId); - std::thread t2(OpenCloseDatabase, storeId); - std::thread t3(OpenCloseDatabase, storeId); - std::thread t4(OpenCloseDatabase, storeId); - t1.join(); - t2.join(); - t3.join(); - t4.join(); - EXPECT_EQ(g_mgr.DeleteKvStore(storeId), OK); + ASSERT_NO_FATAL_FAILURE(FreqOpenClose001()); } /** @@ -1407,6 +1419,56 @@ HWTEST_F(DistributedDBInterfacesDatabaseTest, CompressionRate1, TestSize.Level1) EXPECT_EQ(g_mgr.DeleteKvStore(storeId), OK); } +/** + * @tc.name: CompressionRate2 + * @tc.desc: Open the kv store with again with different compression option. + * @tc.type: FUNC + * @tc.require: + * @tc.author: lianhuix + */ +HWTEST_F(DistributedDBInterfacesDatabaseTest, CompressionRate2, TestSize.Level1) +{ + /** + * @tc.steps: step1. Open the kv store with the option that comressionRate is invalid. + * @tc.expected: step1. Open kv store successfully. Returns OK. + */ + KvStoreNbDelegate::Option option; + option.isNeedCompressOnSync = true; + option.compressionRate = 70; // 70 compression rate. + const std::string storeId("CompressionRate1"); + g_mgr.GetKvStore(storeId, option, g_kvNbDelegateCallback); + ASSERT_TRUE(g_kvNbDelegatePtr != nullptr); + EXPECT_TRUE(g_kvDelegateStatus == OK); + + /** + * @tc.steps: step2. Open again with different compression option + * @tc.expected: step2. Open kv store failed. Returns INVALID_ARGS. + */ + DBStatus status; + KvStoreNbDelegate *delegate = nullptr; + auto callback = bind(&DistributedDBToolsUnitTest::KvStoreNbDelegateCallback, + placeholders::_1, placeholders::_2, std::ref(status), std::ref(delegate)); + + option.compressionRate = 80; // 80 compression rate. + g_mgr.GetKvStore(storeId, option, callback); + ASSERT_TRUE(delegate == nullptr); + EXPECT_TRUE(status == INVALID_ARGS); + + option.isNeedCompressOnSync = false; + option.compressionRate = 70; // 70 compression rate. + g_mgr.GetKvStore(storeId, option, callback); + ASSERT_TRUE(delegate == nullptr); + EXPECT_TRUE(status == INVALID_ARGS); + + /** + * @tc.steps: step3. Close kv store + * @tc.expected: step3. OK. + */ + g_mgr.CloseKvStore(g_kvNbDelegatePtr); + g_kvNbDelegatePtr = nullptr; + EXPECT_EQ(g_mgr.DeleteKvStore(storeId), OK); +} + HWTEST_F(DistributedDBInterfacesDatabaseTest, DataInterceptor1, TestSize.Level1) { /** diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_device_identifier_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_device_identifier_test.cpp index 7cb509e4..b670fdba 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_device_identifier_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_device_identifier_test.cpp @@ -519,6 +519,18 @@ HWTEST_F(DistributedDBDeviceIdentifierTest, StorageEngineTest001, TestSize.Level storageEngine->Release(); } +namespace { +void StorageEngineTest002() +{ + std::string exportFileName = g_testDir + "/" + STORE_ID + ".dump"; + int fd = open(exportFileName.c_str(), (O_WRONLY | O_CREAT), (S_IRUSR | S_IWUSR | S_IRGRP)); + ASSERT_TRUE(fd >= 0); + g_store->Dump(fd); + close(fd); + OS::RemoveDBDirectory(exportFileName); +} +} + /** * @tc.name: StorageEngineTest002 * @tc.desc: Test the interface of Dump @@ -528,12 +540,7 @@ HWTEST_F(DistributedDBDeviceIdentifierTest, StorageEngineTest001, TestSize.Level */ HWTEST_F(DistributedDBDeviceIdentifierTest, StorageEngineTest002, TestSize.Level1) { - std::string exportFileName = g_testDir + "/" + STORE_ID + ".dump"; - int fd = open(exportFileName.c_str(), (O_WRONLY | O_CREAT), (S_IRUSR | S_IWUSR | S_IRGRP)); - ASSERT_TRUE(fd >= 0); - g_store->Dump(fd); - close(fd); - OS::RemoveDBDirectory(exportFileName); + ASSERT_NO_FATAL_FAILURE(StorageEngineTest002()); } /** diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_encrypt_delegate_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_encrypt_delegate_test.cpp index 938c0ff8..1d15ede5 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_encrypt_delegate_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_encrypt_delegate_test.cpp @@ -542,17 +542,6 @@ HWTEST_F(DistributedDBInterfacesEncryptDelegateTest, EncryptedDbSwitch004, TestS EXPECT_EQ(g_mgr.DeleteKvStore(STORE_ID1), OK); } -/** - * @tc.name: EncryptedDbSwitch008 - * @tc.desc: Test the multi version db Rekey function return BUSY because of Snapshot not close. - * @tc.type: FUNC - * @tc.require: AR000CQDT7 - * @tc.author: wumin - */ -HWTEST_F(DistributedDBInterfacesEncryptDelegateTest, EncryptedDbSwitch008, TestSize.Level1) -{ -} - /** * @tc.name: EncryptedDbSwitch009 * @tc.desc: Test the single version db Rekey function from password1 to password2. diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_nb_delegate_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_nb_delegate_test.cpp index 367c7465..4b33abb7 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_nb_delegate_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_nb_delegate_test.cpp @@ -177,7 +177,7 @@ namespace { return false; } - static const std::string selectSQL = "select timestamp from sync_data order by rowid;"; + std::string selectSQL = "select timestamp from sync_data order by rowid;"; sqlite3_stmt *statement = nullptr; EXPECT_EQ(sqlite3_prepare(db, selectSQL.c_str(), -1, &statement, NULL), SQLITE_OK); std::vector timeVect; @@ -2409,6 +2409,58 @@ HWTEST_F(DistributedDBInterfacesNBDelegateTest, LocalStore002, TestSize.Level1) EXPECT_EQ(syncDelegate, nullptr); EXPECT_EQ(openStatus, INVALID_ARGS); EXPECT_EQ(mgr.CloseKvStore(localDelegate), OK); + EXPECT_EQ(mgr.DeleteKvStore(STORE_ID_1), OK); +} + +/** + * @tc.name: PutSync001 + * @tc.desc: put data and sync at same time + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangqiquan + */ +HWTEST_F(DistributedDBInterfacesNBDelegateTest, PutSync001, TestSize.Level3) +{ + /** + * @tc.steps:step1. Create database with localOnly. + * @tc.expected: step1. Returns a non-null store. + */ + KvStoreDelegateManager mgr(APP_ID, USER_ID); + mgr.SetKvStoreConfig(g_config); + const KvStoreNbDelegate::Option option = {true, false, false}; + mgr.GetKvStore(STORE_ID_1, option, g_kvNbDelegateCallback); + ASSERT_TRUE(g_kvNbDelegatePtr != nullptr); + EXPECT_EQ(g_kvDelegateStatus, OK); + /** + * @tc.steps:step2. Put data async. + * @tc.expected: step2. Always returns OK. + */ + std::atomic finish = false; + std::thread putThread([&finish]() { + while (!finish) { + EXPECT_EQ(g_kvNbDelegatePtr->Put(KEY_1, VALUE_1), OK); + } + }); + /** + * @tc.steps:step3. Call sync async. + * @tc.expected: step3. Always returns OK. + */ + std::thread syncThread([]() { + std::vector devices; + devices.emplace_back(""); + Key key = {'k'}; + for (int i = 0; i < 100; ++i) { // sync 100 times + Query query = Query::Select().PrefixKey(key); + DBStatus status = g_kvNbDelegatePtr->Sync(devices, SYNC_MODE_PULL_ONLY, nullptr, query, true); + EXPECT_EQ(status, OK); + } + }); + syncThread.join(); + finish = true; + putThread.join(); + EXPECT_EQ(mgr.CloseKvStore(g_kvNbDelegatePtr), OK); + g_kvNbDelegatePtr = nullptr; + EXPECT_EQ(mgr.DeleteKvStore(STORE_ID_1), OK); } /** @@ -2467,4 +2519,164 @@ HWTEST_F(DistributedDBInterfacesNBDelegateTest, ResultSetLimitTest001, TestSize. EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK); EXPECT_EQ(g_mgr.DeleteKvStore("ResultSetLimitTest001"), OK); g_kvNbDelegatePtr = nullptr; +} + +/** + * @tc.name: UpdateKey001 + * @tc.desc: Test update key + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangqiquan + */ +HWTEST_F(DistributedDBInterfacesNBDelegateTest, UpdateKey001, TestSize.Level0) +{ + /** + * @tc.steps:step1. Create database. + * @tc.expected: step1. Returns a non-null kvstore. + */ + KvStoreNbDelegate::Option option; + g_mgr.GetKvStore("UpdateKey001", option, g_kvNbDelegateCallback); + ASSERT_TRUE(g_kvNbDelegatePtr != nullptr); + EXPECT_TRUE(g_kvDelegateStatus == OK); + /** + * @tc.steps:step2. Put (k1, v1) into the database. + * @tc.expected: step2. Returns OK. + */ + Key k1 = {'k', '1'}; + EXPECT_EQ(g_kvNbDelegatePtr->Put(k1, VALUE_1), OK); + /** + * @tc.steps:step3. Update (k1, v1) to (k10, v1). + * @tc.expected: step3. Returns OK and get k1 return not found. + */ + g_kvNbDelegatePtr->UpdateKey([](const Key &originKey, Key &newKey) { + newKey = originKey; + newKey.push_back('0'); + }); + Value actualValue; + EXPECT_EQ(g_kvNbDelegatePtr->Get(k1, actualValue), NOT_FOUND); + k1.push_back('0'); + EXPECT_EQ(g_kvNbDelegatePtr->Get(k1, actualValue), OK); + EXPECT_EQ(actualValue, VALUE_1); + /** + * @tc.steps:step4. Close store. + * @tc.expected: step4. Returns OK. + */ + EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK); + EXPECT_EQ(g_mgr.DeleteKvStore("UpdateKey001"), OK); + g_kvNbDelegatePtr = nullptr; +} + +/** + * @tc.name: UpdateKey002 + * @tc.desc: Test update key with transaction + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangqiquan + */ +HWTEST_F(DistributedDBInterfacesNBDelegateTest, UpdateKey002, TestSize.Level0) +{ + /** + * @tc.steps:step1. Create database. + * @tc.expected: step1. Returns a non-null kvstore. + */ + KvStoreNbDelegate::Option option; + g_mgr.GetKvStore("UpdateKey002", option, g_kvNbDelegateCallback); + ASSERT_TRUE(g_kvNbDelegatePtr != nullptr); + EXPECT_TRUE(g_kvDelegateStatus == OK); + /** + * @tc.steps:step2. Put (k1, v1) into the database . + * @tc.expected: step2. Returns OK. + */ + Key k1 = {'k', '1'}; + EXPECT_EQ(g_kvNbDelegatePtr->Put(k1, VALUE_1), OK); + g_kvNbDelegatePtr->StartTransaction(); + /** + * @tc.steps:step3. Update (k1, v1) to (k10, v1). + * @tc.expected: step3. Returns OK and get k1 return not found. + */ + g_kvNbDelegatePtr->UpdateKey([](const Key &originKey, Key &newKey) { + newKey = originKey; + newKey.push_back('0'); + }); + Value actualValue; + EXPECT_EQ(g_kvNbDelegatePtr->Get(k1, actualValue), NOT_FOUND); + Key k10 = {'k', '1', '0'}; + EXPECT_EQ(g_kvNbDelegatePtr->Get(k10, actualValue), OK); + EXPECT_EQ(actualValue, VALUE_1); + /** + * @tc.steps:step5. Rollback Transaction. + * @tc.expected: step5. k10 not exist in db. + */ + g_kvNbDelegatePtr->Rollback(); + EXPECT_EQ(g_kvNbDelegatePtr->Get(k10, actualValue), NOT_FOUND); + EXPECT_EQ(g_kvNbDelegatePtr->Get(k1, actualValue), OK); + /** + * @tc.steps:step5. Commit transaction. + * @tc.expected: step5. data exist in db. + */ + g_kvNbDelegatePtr->StartTransaction(); + g_kvNbDelegatePtr->UpdateKey([](const Key &originKey, Key &newKey) { + newKey = originKey; + newKey.push_back('0'); + }); + g_kvNbDelegatePtr->Commit(); + EXPECT_EQ(g_kvNbDelegatePtr->Get(k10, actualValue), OK); + /** + * @tc.steps:step6. Close store. + * @tc.expected: step6. Returns OK. + */ + EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK); + EXPECT_EQ(g_mgr.DeleteKvStore("UpdateKey002"), OK); + g_kvNbDelegatePtr = nullptr; +} + +/** + * @tc.name: UpdateKey003 + * @tc.desc: Test update key with invalid args + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangqiquan + */ +HWTEST_F(DistributedDBInterfacesNBDelegateTest, UpdateKey003, TestSize.Level0) +{ + /** + * @tc.steps:step1. Create database. + * @tc.expected: step1. Returns a non-null kvstore. + */ + KvStoreNbDelegate::Option option; + g_mgr.GetKvStore("UpdateKey003", option, g_kvNbDelegateCallback); + ASSERT_TRUE(g_kvNbDelegatePtr != nullptr); + EXPECT_TRUE(g_kvDelegateStatus == OK); + /** + * @tc.steps:step2. Put (k1, v1) into the database . + * @tc.expected: step2. Returns OK. + */ + Key k1 = {'k', '1'}; + Key k2 = {'k', '2'}; + EXPECT_EQ(g_kvNbDelegatePtr->Put(k1, VALUE_1), OK); + EXPECT_EQ(g_kvNbDelegatePtr->Put(k2, VALUE_1), OK); + /** + * @tc.steps:step3. Update key with nullptr or invalid key. + * @tc.expected: step3. Returns INVALID_ARGS. + */ + EXPECT_EQ(g_kvNbDelegatePtr->UpdateKey(nullptr), INVALID_ARGS); + DBStatus status = g_kvNbDelegatePtr->UpdateKey([](const Key &originKey, Key &newKey) { + newKey.clear(); + }); + EXPECT_EQ(status, INVALID_ARGS); + status = g_kvNbDelegatePtr->UpdateKey([](const Key &originKey, Key &newKey) { + newKey.assign(2048u, '0'); // 2048 is invalid len + }); + EXPECT_EQ(status, INVALID_ARGS); + status = g_kvNbDelegatePtr->UpdateKey([](const Key &originKey, Key &newKey) { + newKey = {'k', '3'}; + }); + EXPECT_EQ(status, CONSTRAINT); + /** + * @tc.steps:step4. Close store. + * @tc.expected: step4. Returns OK. + */ + EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK); + EXPECT_EQ(g_mgr.DeleteKvStore("UpdateKey003"), OK); + g_kvNbDelegatePtr = nullptr; } \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_relational_sync_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_relational_sync_test.cpp index 6fb13ca5..a974f4a7 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_relational_sync_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_relational_sync_test.cpp @@ -71,6 +71,15 @@ namespace { level INTEGER ))""; + const std::string ALL_FIELD_TYPE_TABLE_SQL = R""(CREATE TABLE IF NOT EXISTS tbl_all_type( + id INTEGER PRIMARY KEY, + f_int INT, + f_real REAL, + f_text TEXT, + f_blob BLOB, + f_none + ))""; + void FakeOldVersionDB(sqlite3 *db) { std::string dropTrigger = "DROP TRIGGER IF EXISTS naturalbase_rdb_student_1_ON_UPDATE;"; @@ -851,4 +860,166 @@ HWTEST_F(DistributedDBInterfacesRelationalSyncTest, TableFieldsOrderTest002, Tes EXPECT_EQ(sqlite3_column_int64(stmt, 3), 91); // 91 score return OK; }); +} + +/** + * @tc.name: SyncZeroBlobTest001 + * @tc.desc: Sync device with zero blob + * @tc.type: FUNC + * @tc.require: + * @tc.author: lianhuix + */ +HWTEST_F(DistributedDBInterfacesRelationalSyncTest, SyncZeroBlobTest001, TestSize.Level1) +{ + EXPECT_EQ(RelationalTestUtils::ExecSql(db, ALL_FIELD_TYPE_TABLE_SQL), SQLITE_OK); + EXPECT_EQ(delegate->CreateDistributedTable("tbl_all_type"), OK); + AddDeviceSchema(g_deviceB, db, "tbl_all_type"); + + // prepare with zero blob data + std::string insertSql = "INSERT INTO tbl_all_type VALUES(?, ?, ?, ?, ?, ?)"; + int ret = RelationalTestUtils::ExecSql(db, insertSql, [] (sqlite3_stmt *stmt) { + sqlite3_bind_int64(stmt, 1, 1001); // 1, 1001 bind index, bind value + sqlite3_bind_int64(stmt, 2, 12344); // 2, 12344 bind index, bind value + sqlite3_bind_double(stmt, 3, 1.234); // 3, 1.234 bind index, bind value + SQLiteUtils::BindTextToStatement(stmt, 4, ""); // 4, bind index + SQLiteUtils::BindBlobToStatement(stmt, 5, {}); // 5,bind index + return E_OK; + }, nullptr); + EXPECT_EQ(ret, E_OK); + + std::vector devices = {DEVICE_B}; + Query query = Query::Select("tbl_all_type"); + int errCode = delegate->Sync(devices, SyncMode::SYNC_MODE_PUSH_ONLY, query, + [&devices](const std::map> &devicesMap) { + EXPECT_EQ(devicesMap.size(), devices.size()); + for (const auto &itDev : devicesMap) { + for (const auto &itTbl : itDev.second) { + EXPECT_EQ(itTbl.status, OK); + } + } + }, true); + EXPECT_EQ(errCode, OK); + + std::vector data; + g_deviceB->GetAllSyncData("tbl_all_type", data); + EXPECT_EQ(data.size(), 1U); + for (const auto &it : data) { + DataValue val; + it.objectData.GetDataValue("id", val); + EXPECT_EQ(val.GetType(), StorageType::STORAGE_TYPE_INTEGER); + it.objectData.GetDataValue("f_int", val); + EXPECT_EQ(val.GetType(), StorageType::STORAGE_TYPE_INTEGER); + it.objectData.GetDataValue("f_real", val); + EXPECT_EQ(val.GetType(), StorageType::STORAGE_TYPE_REAL); + it.objectData.GetDataValue("f_text", val); + EXPECT_EQ(val.GetType(), StorageType::STORAGE_TYPE_TEXT); + it.objectData.GetDataValue("f_blob", val); + EXPECT_EQ(val.GetType(), StorageType::STORAGE_TYPE_BLOB); + it.objectData.GetDataValue("f_none", val); + EXPECT_EQ(val.GetType(), StorageType::STORAGE_TYPE_NULL); + } +} + +namespace { +struct TblAllType { + DataValue id_; + DataValue fInt_; + DataValue fReal_; + DataValue fText_; + DataValue fBlob_; + DataValue fNone_; + + TblAllType(int64_t id, int64_t fInt, double fReal, const std::string &fText, const Blob &fBlob) + { + id_ = id; + fInt_ = fInt; + fReal_ = fReal; + fText_ = fText; + fBlob_ = fBlob; + } + + VirtualRowData operator() () const + { + VirtualRowData virtualRowData; + virtualRowData.objectData.PutDataValue("id", id_); + virtualRowData.objectData.PutDataValue("f_int", fInt_); + virtualRowData.objectData.PutDataValue("f_real", fReal_); + virtualRowData.objectData.PutDataValue("f_text", fText_); + virtualRowData.objectData.PutDataValue("f_blob", fBlob_); + virtualRowData.objectData.PutDataValue("f_none", fNone_); + + virtualRowData.logInfo.dataKey = 4; // 4 fake datakey + virtualRowData.logInfo.device = DEVICE_B; + virtualRowData.logInfo.originDev = DEVICE_B; + virtualRowData.logInfo.timestamp = 3170194300891338180; // 3170194300891338180 fake timestamp + virtualRowData.logInfo.wTimestamp = 3170194300891338180; // 3170194300891338180 fake timestamp + virtualRowData.logInfo.flag = 2; // 2 fake flag + + std::vector hashKey; + DBCommon::CalcValueHash({}, hashKey); + virtualRowData.logInfo.hashKey = hashKey; + return virtualRowData; + } +}; +} + +/** + * @tc.name: SyncZeroBlobTest002 + * @tc.desc: Sync device with zero blob + * @tc.type: FUNC + * @tc.require: + * @tc.author: lianhuix + */ +HWTEST_F(DistributedDBInterfacesRelationalSyncTest, SyncZeroBlobTest002, TestSize.Level1) +{ + EXPECT_EQ(RelationalTestUtils::ExecSql(db, ALL_FIELD_TYPE_TABLE_SQL), SQLITE_OK); + EXPECT_EQ(delegate->CreateDistributedTable("tbl_all_type"), OK); + AddDeviceSchema(g_deviceB, db, "tbl_all_type"); + + std::vector dataList; + g_deviceB->PutDeviceData("tbl_all_type", + std::vector {{1001, 12344, 1.234, "", {}}}); // 1001, 12344, 1.234 : fake data + + std::vector devices = {DEVICE_B}; + Query query = Query::Select("tbl_all_type"); + int errCode = delegate->Sync(devices, SyncMode::SYNC_MODE_PULL_ONLY, query, + [&devices](const std::map> &devicesMap) { + EXPECT_EQ(devicesMap.size(), devices.size()); + for (const auto &itDev : devicesMap) { + for (const auto &itTbl : itDev.second) { + EXPECT_EQ(itTbl.status, OK); + } + } + }, true); + EXPECT_EQ(errCode, OK); + + std::string devictTbl = RelationalStoreManager::GetDistributedTableName(DEVICE_B, "tbl_all_type"); + std::string insertSql = "SELECT * FROM " + devictTbl; + int resCnt = 0; + int ret = RelationalTestUtils::ExecSql(db, insertSql, nullptr, [&resCnt](sqlite3_stmt *stmt) { + EXPECT_EQ(sqlite3_column_type(stmt, 0), SQLITE_INTEGER); + EXPECT_EQ(sqlite3_column_int(stmt, 0), 1001); // 1001: fake data + + EXPECT_EQ(sqlite3_column_type(stmt, 1), SQLITE_INTEGER); // 1: column index + EXPECT_EQ(sqlite3_column_int(stmt, 1), 12344); // 1: column index; 12344: fake data + + EXPECT_EQ(sqlite3_column_type(stmt, 2), SQLITE_FLOAT); // 2: column index + EXPECT_EQ(sqlite3_column_double(stmt, 2), 1.234); // 2: column index; 1.234: fake data + + EXPECT_EQ(sqlite3_column_type(stmt, 3), SQLITE_TEXT); // 3: column index + std::string strVal; + SQLiteUtils::GetColumnTextValue(stmt, 3, strVal); // 3: column index + EXPECT_EQ(strVal, ""); + + EXPECT_EQ(sqlite3_column_type(stmt, 4), SQLITE_BLOB); // 4: column index + std::vector blobVal; + SQLiteUtils::GetColumnBlobValue(stmt, 4, blobVal); // 4: column index + EXPECT_EQ(blobVal, std::vector {}); + + EXPECT_EQ(sqlite3_column_type(stmt, 5), SQLITE_NULL); // 5: column index + resCnt++; + return E_OK; + }); + EXPECT_EQ(resCnt, 1); + EXPECT_EQ(ret, E_OK); } \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_relational_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_relational_test.cpp index dacc87d2..52e3b789 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_relational_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_relational_test.cpp @@ -729,9 +729,15 @@ HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalRemoveDeviceDataTest00 * @tc.steps:step3. Remove device data * @tc.expected: step3. ok */ + EXPECT_EQ(delegate->RemoveDeviceData("DEVICE_A"), DISTRIBUTED_SCHEMA_NOT_FOUND); + EXPECT_EQ(delegate->RemoveDeviceData("DEVICE_D"), DISTRIBUTED_SCHEMA_NOT_FOUND); + EXPECT_EQ(delegate->RemoveDeviceData("DEVICE_A", "sync_data"), DISTRIBUTED_SCHEMA_NOT_FOUND); + EXPECT_EQ(delegate->CreateDistributedTable("sync_data"), OK); EXPECT_EQ(delegate->RemoveDeviceData("DEVICE_A"), OK); EXPECT_EQ(delegate->RemoveDeviceData("DEVICE_B"), OK); EXPECT_EQ(delegate->RemoveDeviceData("DEVICE_C", "sync_data"), OK); + EXPECT_EQ(delegate->RemoveDeviceData("DEVICE_D"), OK); + EXPECT_EQ(delegate->RemoveDeviceData("DEVICE_A", "sync_data_A"), DISTRIBUTED_SCHEMA_NOT_FOUND); /** * @tc.steps:step4. Remove device data with invalid args @@ -830,7 +836,7 @@ HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalRemoveDeviceDataTest00 EXPECT_EQ(delegate->RemoveDeviceData(DEVICE_B), OK); int logCnt = -1; - std::string checkLogSql = "SELECT count(*) FROM naturalbase_rdb_aux_t1_log WHERE device = '" + DEVICE_B + "'"; + std::string checkLogSql = "SELECT count(*) FROM naturalbase_rdb_aux_t1_log"; RelationalTestUtils::ExecSql(db, checkLogSql, nullptr, [&logCnt](sqlite3_stmt *stmt) { logCnt = sqlite3_column_int(stmt, 0); return E_OK; @@ -839,7 +845,7 @@ HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalRemoveDeviceDataTest00 int dataCnt = -1; std::string deviceTable = g_mgr.GetDistributedTableName(DEVICE_B, "t1"); - std::string checkDataSql = "SELECT count(*) FROM " + deviceTable + " WHERE device = '" + DEVICE_B + "'"; + std::string checkDataSql = "SELECT count(*) FROM " + deviceTable; RelationalTestUtils::ExecSql(db, checkDataSql, nullptr, [&dataCnt](sqlite3_stmt *stmt) { dataCnt = sqlite3_column_int(stmt, 0); return E_OK; @@ -851,6 +857,138 @@ HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalRemoveDeviceDataTest00 EXPECT_EQ(sqlite3_close_v2(db), SQLITE_OK); } +void TestRemoveDeviceDataWithCallback(bool removeAll) +{ + /** + * @tc.steps:step1. Prepare db and data + * @tc.expected: step1. Return OK. + */ + RuntimeConfig::SetTranslateToDeviceIdCallback([](const std::string &oriDevId, const StoreInfo &info) { + return oriDevId + "_" + info.appId; + }); + sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX); + ASSERT_NE(db, nullptr); + EXPECT_EQ(RelationalTestUtils::ExecSql(db, "PRAGMA journal_mode=WAL;"), SQLITE_OK); + EXPECT_EQ(RelationalTestUtils::ExecSql(db, SIMPLE_CREATE_TABLE_SQL), SQLITE_OK); + AddDeviceSchema(g_deviceB, db, "t1"); + RelationalStoreDelegate *delegate = nullptr; + DBStatus status = g_mgr.OpenStore(g_dbDir + STORE_ID + DB_SUFFIX, STORE_ID, {}, delegate); + EXPECT_EQ(status, OK); + ASSERT_NE(delegate, nullptr); + EXPECT_EQ(delegate->CreateDistributedTable("t1"), OK); + g_deviceB->PutDeviceData("t1", std::vector { + {1, "111", 1, 0, 1} // test data + }); + std::vector devices = {DEVICE_B}; + Query query = Query::Select("t1").EqualTo("a", 1); + status = delegate->Sync(devices, SyncMode::SYNC_MODE_PULL_ONLY, query, + [&devices](const std::map> &devicesMap) { + ASSERT_EQ(devicesMap.size(), devices.size()); + EXPECT_EQ(devicesMap.at(DEVICE_B)[0].status, OK); + }, true); + EXPECT_EQ(status, OK); + /** + * @tc.steps:step2. remove device data and check table + * @tc.expected: step2. dev table not exist and log not exist device b. + */ + std::this_thread::sleep_for(std::chrono::seconds(1)); + if (removeAll) { + EXPECT_EQ(delegate->RemoveDeviceData(), OK); + } else { + EXPECT_EQ(delegate->RemoveDeviceData(DEVICE_B + "_" + APP_ID), OK); + } + int logCnt = -1; + std::string checkLogSql = "SELECT count(*) FROM naturalbase_rdb_aux_t1_log"; + RelationalTestUtils::ExecSql(db, checkLogSql, nullptr, [&logCnt](sqlite3_stmt *stmt) { + logCnt = sqlite3_column_int(stmt, 0); + return E_OK; + }); + EXPECT_EQ(logCnt, 0); + std::string deviceTable = RelationalStoreManager::GetDistributedTableName(DEVICE_B + "_" + APP_ID, "t1"); + std::string checkDataSql = "SELECT count(*) FROM " + deviceTable; + EXPECT_NE(RelationalTestUtils::ExecSql(db, checkDataSql, nullptr, nullptr), SQLITE_OK); + /** + * @tc.steps:step3. close db + * @tc.expected: step3. Return OK. + */ + status = g_mgr.CloseStore(delegate); + EXPECT_EQ(status, OK); + EXPECT_EQ(sqlite3_close_v2(db), SQLITE_OK); + RuntimeConfig::SetTranslateToDeviceIdCallback(nullptr); +} +/** + * @tc.name: RelationalRemoveDeviceDataTest003 + * @tc.desc: Test remove all device data and sync again + * @tc.type: FUNC + * @tc.require: AR000GK58F + * @tc.author: zhangqiquan + */ +HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalRemoveDeviceDataTest003, TestSize.Level1) +{ + TestRemoveDeviceDataWithCallback(true); +} + +/** + * @tc.name: RelationalRemoveDeviceDataTest004 + * @tc.desc: Test remove one device data and sync again + * @tc.type: FUNC + * @tc.require: AR000GK58F + * @tc.author: zhangqiquan + */ +HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalRemoveDeviceDataTest004, TestSize.Level1) +{ + TestRemoveDeviceDataWithCallback(false); +} + +/** + * @tc.name: RelationalRemoveDeviceDataTest005 + * @tc.desc: Test remove device data with invalid param + * @tc.type: FUNC + * @tc.require: AR000GK58F + * @tc.author: zhangqiquan + */ +HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalRemoveDeviceDataTest005, TestSize.Level1) +{ + /** + * @tc.steps:step1. Prepare db file + * @tc.expected: step1. Return OK. + */ + sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX); + ASSERT_NE(db, nullptr); + EXPECT_EQ(RelationalTestUtils::ExecSql(db, "PRAGMA journal_mode=WAL;"), SQLITE_OK); + EXPECT_EQ(RelationalTestUtils::ExecSql(db, NORMAL_CREATE_TABLE_SQL), SQLITE_OK); + RelationalTestUtils::CreateDeviceTable(db, "sync_data", "DEVICE_A"); + AddDeviceSchema(g_deviceB, db, "sync_data"); + /** + * @tc.steps:step2. Open store + * @tc.expected: step2. return OK + */ + RelationalStoreDelegate *delegate = nullptr; + DBStatus status = g_mgr.OpenStore(g_dbDir + STORE_ID + DB_SUFFIX, STORE_ID, {}, delegate); + EXPECT_EQ(status, OK); + ASSERT_NE(delegate, nullptr); + int count = 0; + RuntimeConfig::SetTranslateToDeviceIdCallback([&count](const std::string &oriDevId, const StoreInfo &info) { + count++; + return oriDevId + "_" + info.appId; + }); + /** + * @tc.steps:step3. Remove not exist device data + * @tc.expected: step3. ok + */ + EXPECT_EQ(delegate->CreateDistributedTable("sync_data"), OK); + EXPECT_EQ(delegate->RemoveDeviceData("DEVICE_C", "sync_data"), OK); + EXPECT_EQ(count, 0); + /** + * @tc.steps:step4. Close store + * @tc.expected: step4 Return OK. + */ + status = g_mgr.CloseStore(delegate); + EXPECT_EQ(status, OK); + EXPECT_EQ(sqlite3_close_v2(db), SQLITE_OK); + RuntimeConfig::SetTranslateToDeviceIdCallback(nullptr); +} + /** * @tc.name: RelationalOpenStorePathCheckTest001 * @tc.desc: Test open store with same label but different path. @@ -1067,4 +1205,30 @@ HWTEST_F(DistributedDBInterfacesRelationalTest, SqliteKeyWordTest001, TestSize.L EXPECT_EQ(status, OK); delegate = nullptr; EXPECT_EQ(sqlite3_close_v2(db), SQLITE_OK); +} + +/** + * @tc.name: GetDistributedTableName001 + * @tc.desc: Test get distributed table name + * @tc.type: FUNC + * @tc.require: AR000GK58F + * @tc.author: zhangqiquan + */ +HWTEST_F(DistributedDBInterfacesRelationalTest, GetDistributedTableName001, TestSize.Level1) +{ + const std::string deviceName = "DEVICES_A"; + const std::string tableName = "TABLE"; + const std::string hashDev = DBCommon::TransferStringToHex(DBCommon::TransferHashString(deviceName)); + + std::string devTableName = RelationalStoreManager::GetDistributedTableName(deviceName, tableName); + EXPECT_EQ(devTableName, DBConstant::RELATIONAL_PREFIX + tableName + "_" + hashDev); + RuntimeConfig::SetTranslateToDeviceIdCallback([](const std::string &oriDevId, const StoreInfo &info) { + EXPECT_EQ(info.appId, ""); + return oriDevId; + }); + devTableName = RelationalStoreManager::GetDistributedTableName(deviceName, tableName); + EXPECT_EQ(devTableName, DBConstant::RELATIONAL_PREFIX + tableName + "_" + deviceName); + devTableName = RelationalStoreManager::GetDistributedTableName("", tableName); + EXPECT_EQ(devTableName, DBConstant::RELATIONAL_PREFIX + tableName + "_"); + RuntimeConfig::SetTranslateToDeviceIdCallback(nullptr); } \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/runtime_context_process_system_api_adapter_impl_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/runtime_context_process_system_api_adapter_impl_test.cpp index efc54f8b..92b14a33 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/runtime_context_process_system_api_adapter_impl_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/runtime_context_process_system_api_adapter_impl_test.cpp @@ -241,20 +241,13 @@ void FuncCheckDeviceSecurityAbility() RuntimeContext::GetInstance()->CheckDeviceSecurityAbility("", SecurityOption()); return; } -} -/** - * @tc.name: CheckDeviceSecurityAbility002 - * @tc.desc: Check device security ability with getkvstore frequency. - * @tc.type: FUNC - * @tc.require: AR000EV1G2 - */ -HWTEST_F(RuntimeContextProcessSystemApiAdapterImplTest, CheckDeviceSecurityAbility002, TestSize.Level1) +void CheckDeviceSecurityAbility002() { g_config.dataDir = g_testDir; - g_mgr.SetKvStoreConfig(g_config); + EXPECT_EQ(g_mgr.SetKvStoreConfig(g_config), OK); - RuntimeContext::GetInstance()->SetProcessSystemApiAdapter(g_adapter); + EXPECT_EQ(RuntimeContext::GetInstance()->SetProcessSystemApiAdapter(g_adapter), E_OK); g_adapter->SetNeedCreateDb(true); const std::string storeId = "CheckDeviceSecurityAbility002"; @@ -264,14 +257,24 @@ HWTEST_F(RuntimeContextProcessSystemApiAdapterImplTest, CheckDeviceSecurityAbili LOGI("open store!!"); KvStoreNbDelegate::Option option1 = {true, false, false}; g_mgr.GetKvStore(storeId, option1, g_kvNbDelegateCallback); - g_mgr.CloseKvStore(g_kvNbDelegatePtr); + EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK); } }); - std::thread t3(FuncCheckDeviceSecurityAbility); t1.join(); t2.join(); - t3.join(); +} +} + +/** + * @tc.name: CheckDeviceSecurityAbility002 + * @tc.desc: Check device security ability with getkvstore frequency. + * @tc.type: FUNC + * @tc.require: AR000EV1G2 + */ +HWTEST_F(RuntimeContextProcessSystemApiAdapterImplTest, CheckDeviceSecurityAbility002, TestSize.Level1) +{ + ASSERT_NO_FATAL_FAILURE(CheckDeviceSecurityAbility002()); } /** diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_relational_get_data_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_relational_get_data_test.cpp index 28c64083..96c3498d 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_relational_get_data_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_relational_get_data_test.cpp @@ -261,6 +261,23 @@ void SetRemoteSchema(const RelationalSyncAbleStorage *store, const std::string & uint8_t remoteSchemaType = static_cast(store->GetSchemaInfo().GetSchemaType()); const_cast(store)->SaveRemoteDeviceSchema(deviceID, remoteSchema, remoteSchemaType); } + +void SetNextBeginTime001() +{ + QueryObject query(Query::Select(g_tableName)); + std::unique_ptr token = + std::make_unique(SyncTimeRange {}, query); + ASSERT_TRUE(token != nullptr); + + DataItem dataItem; + dataItem.timestamp = INT64_MAX; + token->SetNextBeginTime(dataItem); + + dataItem.flag = DataItem::DELETE_FLAG; + token->FinishGetData(); + EXPECT_EQ(token->IsGetAllDataFinished(), false); + token->SetNextBeginTime(dataItem); +} } class DistributedDBRelationalGetDataTest : public testing::Test { @@ -1596,18 +1613,7 @@ HWTEST_F(DistributedDBRelationalGetDataTest, SetSchema1, TestSize.Level1) */ HWTEST_F(DistributedDBRelationalGetDataTest, SetNextBeginTime001, TestSize.Level1) { - QueryObject query(Query::Select(g_tableName)); - std::unique_ptr token = - std::make_unique(SyncTimeRange {}, query); - ASSERT_TRUE(token != nullptr); - - DataItem dataItem; - dataItem.timestamp = INT64_MAX; - token->SetNextBeginTime(dataItem); - - dataItem.flag = DataItem::DELETE_FLAG; - token->FinishGetData(); - token->SetNextBeginTime(dataItem); + ASSERT_NO_FATAL_FAILURE(SetNextBeginTime001()); } /** diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_single_ver_natural_store_testcase.h b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_single_ver_natural_store_testcase.h index 72c514e5..0846199c 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_single_ver_natural_store_testcase.h +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_single_ver_natural_store_testcase.h @@ -12,6 +12,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#ifndef DISTRIBUTEDDB_STORAGE_SINGLE_VER_NATURAL_STORE_TESTCASE_H +#define DISTRIBUTEDDB_STORAGE_SINGLE_VER_NATURAL_STORE_TESTCASE_H #include #include "db_errno.h" @@ -23,8 +25,6 @@ #include "sqlite_single_ver_natural_store_connection.h" #include "sqlite_utils.h" -#ifndef DISTRIBUTEDDB_STORAGE_SINGLE_VER_NATURAL_STORE_TESTCASE_H -#define DISTRIBUTEDDB_STORAGE_SINGLE_VER_NATURAL_STORE_TESTCASE_H struct SyncData { std::vector hashKey; std::vector key; diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_sqlite_single_ver_natural_executor_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_sqlite_single_ver_natural_executor_test.cpp index 6467e541..71805b5f 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_sqlite_single_ver_natural_executor_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_sqlite_single_ver_natural_executor_test.cpp @@ -54,7 +54,7 @@ public: void DistributedDBStorageSQLiteSingleVerNaturalExecutorTest::SetUpTestCase(void) { DistributedDBToolsUnitTest::TestDirInit(g_testDir); - LOGD("DistributedDBStorageSQLiteSingleVerNaturalExecutorTest dir is %s", g_testDir.c_str()); + LOGI("DistributedDBStorageSQLiteSingleVerNaturalExecutorTest dir is %s", g_testDir.c_str()); std::string oriIdentifier = APP_ID + "-" + USER_ID + "-" + "TestGeneralNBExecutor"; std::string identifier = DBCommon::TransferHashString(oriIdentifier); g_identifier = DBCommon::TransferStringToHex(identifier); @@ -454,7 +454,8 @@ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalExecutorTest, InvalidParam011 uint64_t version = 0u; EXPECT_EQ(executor->GetMinVersionCacheData(vec, version), E_OK); EXPECT_EQ(executor->GetMaxVersionInCacheDb(version), E_OK); - EXPECT_EQ(executor->RemoveDeviceDataInCacheMode("device1", true, 0u), E_OK); + std::string hashDev = DBCommon::TransferHashString("device1"); + EXPECT_EQ(executor->RemoveDeviceDataInCacheMode(hashDev, true, 0u), E_OK); sqlite3_close_v2(sqlHandle); sqlHandle = nullptr; } @@ -878,7 +879,8 @@ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalExecutorTest, ExecutorCache00 std::vector keys; EXPECT_EQ(g_handle->DeleteMetaData(keys), SQL_STATE_ERR); EXPECT_EQ(g_handle->PrepareForSavingCacheData(SingleVerDataType::LOCAL_TYPE), SQL_STATE_ERR); - EXPECT_EQ(g_handle->RemoveDeviceDataInCacheMode("device1", true, 0u), SQL_STATE_ERR); + std::string hashDev = DBCommon::TransferHashString("device1"); + EXPECT_EQ(g_handle->RemoveDeviceDataInCacheMode(hashDev, true, 0u), SQL_STATE_ERR); Timestamp timestamp; EXPECT_EQ(g_handle->GetMaxTimestampDuringMigrating(timestamp), -E_NOT_INIT); EXPECT_EQ(g_handle->ResetForSavingCacheData(SingleVerDataType::LOCAL_TYPE), E_OK); @@ -926,7 +928,6 @@ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalExecutorTest, ExecutorCache00 /** * @tc.steps: step3. Change executor to MAIN_ATTACH_CACHE - * @tc.expected: step3. Expect SQL_STATE_ERR */ auto executor2 = std::make_unique( sqlHandle, false, false, ExecutorState::MAIN_ATTACH_CACHE); diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_subscribe_query_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_subscribe_query_test.cpp index 7248ae2f..c4857786 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_subscribe_query_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_subscribe_query_test.cpp @@ -815,4 +815,50 @@ HWTEST_F(DistributedDBStorageSubscribeQueryTest, AddSubscribeTest003, TestSize.L */ RefObject::KillAndDecObjRef(store); KvDBManager::ReleaseDatabaseConnection(conn); +} + +/** + * @tc.name: AddSubscribeTest004 + * @tc.desc: Add subscribe with query by prefixKey + * @tc.type: FUNC + * @tc.require: + * @tc.author: xulianhui + */ +HWTEST_F(DistributedDBStorageSubscribeQueryTest, AddSubscribeTest004, TestSize.Level1) +{ + /** + * @tc.steps:step1. Create a json schema db, get the natural store instance. + * @tc.expected: Get results OK and non-null store. + */ + SQLiteSingleVerNaturalStoreConnection *conn = nullptr; + SQLiteSingleVerNaturalStore *store = nullptr; + CreateAndGetStore("SubscribeTest02", "", conn, store); + + /** + * @tc.steps:step2. Add subscribe with query by prefixKey + * @tc.expected: step2. add success + */ + Query query = Query::Select().PrefixKey(NULL_KEY_1); + QueryObject queryObj(query); + int errCode = store->AddSubscribe(SUBSCRIBE_ID, queryObj, false); + EXPECT_EQ(errCode, E_OK); + + IOption syncIOpt {IOption::SYNC_DATA}; + EXPECT_EQ(conn->Put(syncIOpt, KEY_1, {}), E_OK); + + Value valGot; + EXPECT_EQ(conn->Get(syncIOpt, KEY_1, valGot), E_OK); + EXPECT_EQ(valGot, Value {}); + + std::string subKey = DBConstant::SUBSCRIBE_QUERY_PREFIX + DBCommon::TransferHashString(SUBSCRIBE_ID); + Key metaKey(subKey.begin(), subKey.end()); + EXPECT_EQ(store->GetMetaData(metaKey, valGot), E_OK); + EXPECT_NE(valGot.size(), 0u); + + /** + * @tc.steps:step3. Close natural store + * @tc.expected: step3. Close ok + */ + RefObject::KillAndDecObjRef(store); + KvDBManager::ReleaseDatabaseConnection(conn); } \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_mock_sync_module_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_mock_sync_module_test.cpp index 9e688a50..5ab5ce60 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_mock_sync_module_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_mock_sync_module_test.cpp @@ -62,9 +62,9 @@ public: { syncer_.LocalDataChanged(static_cast(SQLiteGeneralNSNotificationEventType::SQLITE_GENERAL_NS_PUT_EVENT)); } - void Close() + int Close() { - syncer_.Close(true); + return syncer_.Close(true); } private: SyncerProxy syncer_; @@ -117,6 +117,7 @@ void Init(MockSingleVerStateMachine &stateMachine, MockSyncTaskContext *syncTask MockCommunicator &communicator, VirtualSingleVerSyncDBInterface *dbSyncInterface) { std::shared_ptr metadata = std::make_shared(); + ASSERT_EQ(metadata->Initialize(dbSyncInterface), E_OK); (void)syncTaskContext->Initialize("device", dbSyncInterface, metadata, &communicator); (void)stateMachine.Initialize(syncTaskContext, dbSyncInterface, metadata, &communicator); } @@ -166,6 +167,218 @@ void ConstructPacel(Parcel &parcel, uint32_t conditionCount, const std::string & parcel.WriteString(key); parcel.WriteString(value); } + +void StateMachineCheck013() +{ + MockSingleVerStateMachine stateMachine; + auto *syncTaskContext = new (std::nothrow) MockSyncTaskContext(); + auto *dbSyncInterface = new (std::nothrow) VirtualSingleVerSyncDBInterface(); + ASSERT_NE(syncTaskContext, nullptr); + EXPECT_NE(dbSyncInterface, nullptr); + if (dbSyncInterface == nullptr) { + RefObject::KillAndDecObjRef(syncTaskContext); + return; + } + MockCommunicator communicator; + Init(stateMachine, syncTaskContext, communicator, dbSyncInterface); + int count = 0; + EXPECT_CALL(*syncTaskContext, Clear()).WillRepeatedly([&count]() { + count++; + }); + syncTaskContext->RegForkGetDeviceIdFunc([]() { + std::this_thread::sleep_for(std::chrono::seconds(2)); // sleep 2s + }); + auto token = new VirtualContinueToken(); + syncTaskContext->SetContinueToken(static_cast(token)); + RefObject::KillAndDecObjRef(syncTaskContext); + delete dbSyncInterface; + std::this_thread::sleep_for(std::chrono::seconds(5)); // sleep 5s and wait for task exist + EXPECT_EQ(count, 1); +} + +void AutoLaunchCheck001() +{ + MockAutoLaunch mockAutoLaunch; + /** + * @tc.steps: step1. put AutoLaunchItem in cache to simulate a connection was auto launched + */ + std::string id = "TestAutoLaunch"; + std::string userId = "userId"; + AutoLaunchItem item; + mockAutoLaunch.SetAutoLaunchItem(id, userId, item); + EXPECT_CALL(mockAutoLaunch, TryCloseConnection(_)).WillOnce(Return()); + /** + * @tc.steps: step2. send close signal to simulate a connection was unused in 1 min + * @tc.expected: 10 thread try to close the connection and one thread close success + */ + const int loopCount = 10; + int finishCount = 0; + std::mutex mutex; + std::unique_lock lock(mutex); + std::condition_variable cv; + for (int i = 0; i < loopCount; i++) { + std::thread t = std::thread([&finishCount, &mockAutoLaunch, &id, &userId, &mutex, &cv] { + mockAutoLaunch.CallExtConnectionLifeCycleCallbackTask(id, userId); + finishCount++; + if (finishCount == loopCount) { + std::unique_lock lockInner(mutex); + cv.notify_one(); + } + }); + t.detach(); + } + cv.wait(lock, [&finishCount, &loopCount]() { return finishCount == loopCount; }); +} + +void AbilitySync004() +{ + /** + * @tc.steps: step1. set table TEST is permitSync + */ + auto *context = new (std::nothrow) SingleVerKvSyncTaskContext(); + ASSERT_NE(context, nullptr); + /** + * @tc.steps: step2. test context recv dbAbility in diff thread + */ + const int loopCount = 1000; + std::atomic finishCount = 0; + std::mutex mutex; + std::unique_lock lock(mutex); + std::condition_variable cv; + for (int i = 0; i < loopCount; i++) { + std::thread t = std::thread([&context, &finishCount, &cv] { + DbAbility dbAbility; + context->SetDbAbility(dbAbility); + finishCount++; + if (finishCount == loopCount) { + cv.notify_one(); + } + }); + t.detach(); + } + cv.wait(lock, [&]() { return finishCount == loopCount; }); + EXPECT_EQ(context->GetRemoteCompressAlgoStr(), "none"); + RefObject::KillAndDecObjRef(context); +} + +void SyncLifeTest001() +{ + std::shared_ptr syncer = std::make_shared(); + VirtualCommunicatorAggregator *virtualCommunicatorAggregator = new VirtualCommunicatorAggregator(); + ASSERT_NE(virtualCommunicatorAggregator, nullptr); + RuntimeContext::GetInstance()->SetCommunicatorAggregator(virtualCommunicatorAggregator); + VirtualSingleVerSyncDBInterface *syncDBInterface = new VirtualSingleVerSyncDBInterface(); + ASSERT_NE(syncDBInterface, nullptr); + EXPECT_EQ(syncer->Initialize(syncDBInterface, true), -E_INVALID_ARGS); + syncer->EnableAutoSync(true); + for (int i = 0; i < 1000; i++) { // trigger 1000 times auto sync check + syncer->LocalDataChanged(static_cast(SQLiteGeneralNSNotificationEventType::SQLITE_GENERAL_NS_PUT_EVENT)); + } + EXPECT_EQ(virtualCommunicatorAggregator->GetOnlineDevices().size(), 0u); + syncer = nullptr; + RuntimeContext::GetInstance()->SetCommunicatorAggregator(nullptr); + delete syncDBInterface; +} + +void SyncLifeTest002() +{ + std::shared_ptr syncer = std::make_shared(); + VirtualCommunicatorAggregator *virtualCommunicatorAggregator = new VirtualCommunicatorAggregator(); + ASSERT_NE(virtualCommunicatorAggregator, nullptr); + RuntimeContext::GetInstance()->SetCommunicatorAggregator(virtualCommunicatorAggregator); + const std::string DEVICE_B = "deviceB"; + VirtualSingleVerSyncDBInterface *syncDBInterface = new VirtualSingleVerSyncDBInterface(); + ASSERT_NE(syncDBInterface, nullptr); + std::string userId = "userid_0"; + std::string storeId = "storeId_0"; + std::string appId = "appid_0"; + std::string identifier = KvStoreDelegateManager::GetKvStoreIdentifier(userId, appId, storeId); + std::vector identifierVec(identifier.begin(), identifier.end()); + syncDBInterface->SetIdentifier(identifierVec); + for (int i = 0; i < 100; i++) { // run 100 times + EXPECT_EQ(syncer->Initialize(syncDBInterface, true), E_OK); + syncer->EnableAutoSync(true); + virtualCommunicatorAggregator->OnlineDevice(DEVICE_B); + std::thread writeThread([syncer]() { + syncer->LocalDataChanged( + static_cast(SQLiteGeneralNSNotificationEventType::SQLITE_GENERAL_NS_PUT_EVENT)); + }); + std::thread closeThread([syncer, &syncDBInterface]() { + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + EXPECT_EQ(syncer->Close(true), E_OK); + }); + closeThread.join(); + writeThread.join(); + } + syncer = nullptr; + std::this_thread::sleep_for(std::chrono::seconds(1)); + RuntimeContext::GetInstance()->SetCommunicatorAggregator(nullptr); + delete syncDBInterface; +} + +void SyncLifeTest003() +{ + VirtualCommunicatorAggregator *virtualCommunicatorAggregator = new VirtualCommunicatorAggregator(); + ASSERT_NE(virtualCommunicatorAggregator, nullptr); + RuntimeContext::GetInstance()->SetCommunicatorAggregator(virtualCommunicatorAggregator); + TestInterface *syncDBInterface = new TestInterface(); + ASSERT_NE(syncDBInterface, nullptr); + const std::string DEVICE_B = "deviceB"; + std::string userId = "userId_0"; + std::string storeId = "storeId_0"; + std::string appId = "appId_0"; + std::string identifier = KvStoreDelegateManager::GetKvStoreIdentifier(userId, appId, storeId); + std::vector identifierVec(identifier.begin(), identifier.end()); + syncDBInterface->TestSetIdentifier(identifierVec); + syncDBInterface->Initialize(); + virtualCommunicatorAggregator->OnlineDevice(DEVICE_B); + syncDBInterface->TestLocalChange(); + virtualCommunicatorAggregator->OfflineDevice(DEVICE_B); + EXPECT_EQ(syncDBInterface->Close(), E_OK); + RefObject::KillAndDecObjRef(syncDBInterface); + RuntimeContext::GetInstance()->StopTaskPool(); + std::this_thread::sleep_for(std::chrono::seconds(1)); + RuntimeContext::GetInstance()->SetCommunicatorAggregator(nullptr); +} + +void MockRemoteQuery002() +{ + MockRemoteExecutor *executor = new (std::nothrow) MockRemoteExecutor(); + ASSERT_NE(executor, nullptr); + EXPECT_EQ(executor->CallResponseFailed(0, 0, 0, "DEVICE"), -E_BUSY); + RefObject::KillAndDecObjRef(executor); +} + +void SyncerCheck001() +{ + std::shared_ptr syncer = std::make_shared(); + EXPECT_EQ(syncer->SetSyncRetry(true), -E_NOT_INIT); + syncer = nullptr; +} + +void TimeSync001() +{ + auto *communicator = new(std::nothrow) MockCommunicator(); + ASSERT_NE(communicator, nullptr); + auto *storage = new(std::nothrow) VirtualSingleVerSyncDBInterface(); + ASSERT_NE(storage, nullptr); + std::shared_ptr metadata = std::make_shared(); + + EXPECT_CALL(*communicator, SendMessage(_, _, _, _)).WillRepeatedly(Return(DB_ERROR)); + const int loopCount = 100; + const int timeDriverMs = 100; + for (int i = 0; i < loopCount; ++i) { + MockTimeSync timeSync; + EXPECT_EQ(timeSync.Initialize(communicator, metadata, storage, "DEVICES_A"), E_OK); + timeSync.ModifyTimer(timeDriverMs); + std::this_thread::sleep_for(std::chrono::milliseconds(timeDriverMs)); + timeSync.Close(); + } + std::this_thread::sleep_for(std::chrono::seconds(1)); + metadata = nullptr; + delete storage; + delete communicator; +} } class DistributedDBMockSyncModuleTest : public testing::Test { @@ -346,7 +559,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, StateMachineCheck006, TestSize.Level1) // we expect machine don't change context status when queue not empty EXPECT_CALL(syncTaskContext, SetOperationStatus(_)).WillOnce(Return()); EXPECT_CALL(syncTaskContext, SetTaskExecStatus(_)).WillOnce(Return()); - EXPECT_CALL(syncTaskContext, Clear()).WillOnce(Return()); + EXPECT_CALL(syncTaskContext, Clear()).WillRepeatedly(Return()); EXPECT_EQ(stateMachine.CallExecNextTask(), -E_NO_SYNC_TASK); } @@ -489,28 +702,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, StateMachineCheck012, TestSize.Level1) */ HWTEST_F(DistributedDBMockSyncModuleTest, StateMachineCheck013, TestSize.Level1) { - MockSingleVerStateMachine stateMachine; - auto *syncTaskContext = new (std::nothrow) MockSyncTaskContext(); - auto *dbSyncInterface = new (std::nothrow) VirtualSingleVerSyncDBInterface(); - ASSERT_NE(syncTaskContext, nullptr); - EXPECT_NE(dbSyncInterface, nullptr); - if (dbSyncInterface == nullptr) { - RefObject::KillAndDecObjRef(syncTaskContext); - return; - } - MockCommunicator communicator; - Init(stateMachine, syncTaskContext, communicator, dbSyncInterface); - EXPECT_CALL(*syncTaskContext, Clear()).WillRepeatedly(Return()); - syncTaskContext->RegForkGetDeviceIdFunc([]() { - std::this_thread::sleep_for(std::chrono::seconds(2)); // sleep 2s - }); - int token = 1; - int *tokenPtr = &token; - syncTaskContext->SetContinueToken(tokenPtr); - RefObject::KillAndDecObjRef(syncTaskContext); - delete dbSyncInterface; - std::this_thread::sleep_for(std::chrono::seconds(5)); // sleep 5s and wait for task exist - tokenPtr = nullptr; + ASSERT_NO_FATAL_FAILURE(StateMachineCheck013()); } /** @@ -600,6 +792,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, DataSyncCheck003, TestSize.Level1) delete message; } #endif + /** * @tc.name: AutoLaunchCheck001 * @tc.desc: Test autoLaunch close connection. @@ -609,36 +802,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, DataSyncCheck003, TestSize.Level1) */ HWTEST_F(DistributedDBMockSyncModuleTest, AutoLaunchCheck001, TestSize.Level1) { - MockAutoLaunch mockAutoLaunch; - /** - * @tc.steps: step1. put AutoLaunchItem in cache to simulate a connection was auto launched - */ - std::string id = "TestAutoLaunch"; - std::string userId = "userId"; - AutoLaunchItem item; - mockAutoLaunch.SetAutoLaunchItem(id, userId, item); - EXPECT_CALL(mockAutoLaunch, TryCloseConnection(_)).WillOnce(Return()); - /** - * @tc.steps: step2. send close signal to simulate a connection was unused in 1 min - * @tc.expected: 10 thread try to close the connection and one thread close success - */ - const int loopCount = 10; - int finishCount = 0; - std::mutex mutex; - std::unique_lock lock(mutex); - std::condition_variable cv; - for (int i = 0; i < loopCount; i++) { - std::thread t = std::thread([&finishCount, &mockAutoLaunch, &id, &userId, &mutex, &cv] { - mockAutoLaunch.CallExtConnectionLifeCycleCallbackTask(id, userId); - finishCount++; - if (finishCount == loopCount) { - std::unique_lock lockInner(mutex); - cv.notify_one(); - } - }); - t.detach(); - } - cv.wait(lock, [&finishCount, &loopCount]() { return finishCount == loopCount; }); + ASSERT_NO_FATAL_FAILURE(AutoLaunchCheck001()); } /** @@ -833,32 +997,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, AbilitySync003, TestSize.Level1) */ HWTEST_F(DistributedDBMockSyncModuleTest, AbilitySync004, TestSize.Level1) { - /** - * @tc.steps: step1. set table TEST is permitSync - */ - auto *context = new (std::nothrow) SingleVerKvSyncTaskContext(); - ASSERT_NE(context, nullptr); - /** - * @tc.steps: step2. test context recv dbAbility in diff thread - */ - const int loopCount = 1000; - std::atomic finishCount = 0; - std::mutex mutex; - std::unique_lock lock(mutex); - std::condition_variable cv; - for (int i = 0; i < loopCount; i++) { - std::thread t = std::thread([&] { - DbAbility dbAbility; - context->SetDbAbility(dbAbility); - finishCount++; - if (finishCount == loopCount) { - cv.notify_one(); - } - }); - t.detach(); - } - cv.wait(lock, [&]() { return finishCount == loopCount; }); - RefObject::KillAndDecObjRef(context); + ASSERT_NO_FATAL_FAILURE(AbilitySync004()); } /** @@ -870,18 +1009,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, AbilitySync004, TestSize.Level1) */ HWTEST_F(DistributedDBMockSyncModuleTest, SyncLifeTest001, TestSize.Level3) { - std::shared_ptr syncer = std::make_shared(); - VirtualCommunicatorAggregator *virtualCommunicatorAggregator = new VirtualCommunicatorAggregator(); - RuntimeContext::GetInstance()->SetCommunicatorAggregator(virtualCommunicatorAggregator); - VirtualSingleVerSyncDBInterface *syncDBInterface = new VirtualSingleVerSyncDBInterface(); - syncer->Initialize(syncDBInterface, true); - syncer->EnableAutoSync(true); - for (int i = 0; i < 1000; i++) { // trigger 1000 times auto sync check - syncer->LocalDataChanged(static_cast(SQLiteGeneralNSNotificationEventType::SQLITE_GENERAL_NS_PUT_EVENT)); - } - syncer = nullptr; - RuntimeContext::GetInstance()->SetCommunicatorAggregator(nullptr); - delete syncDBInterface; + ASSERT_NO_FATAL_FAILURE(SyncLifeTest001()); } /** @@ -893,36 +1021,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, SyncLifeTest001, TestSize.Level3) */ HWTEST_F(DistributedDBMockSyncModuleTest, SyncLifeTest002, TestSize.Level3) { - std::shared_ptr syncer = std::make_shared(); - VirtualCommunicatorAggregator *virtualCommunicatorAggregator = new VirtualCommunicatorAggregator(); - RuntimeContext::GetInstance()->SetCommunicatorAggregator(virtualCommunicatorAggregator); - const std::string DEVICE_B = "deviceB"; - VirtualSingleVerSyncDBInterface *syncDBInterface = new VirtualSingleVerSyncDBInterface(); - std::string userId = "userid_0"; - std::string storeId = "storeId_0"; - std::string appId = "appid_0"; - std::string identifier = KvStoreDelegateManager::GetKvStoreIdentifier(userId, appId, storeId); - std::vector identifierVec(identifier.begin(), identifier.end()); - syncDBInterface->SetIdentifier(identifierVec); - for (int i = 0; i < 100; i++) { // run 100 times - syncer->Initialize(syncDBInterface, true); - syncer->EnableAutoSync(true); - virtualCommunicatorAggregator->OnlineDevice(DEVICE_B); - std::thread writeThread([syncer]() { - syncer->LocalDataChanged( - static_cast(SQLiteGeneralNSNotificationEventType::SQLITE_GENERAL_NS_PUT_EVENT)); - }); - std::thread closeThread([syncer, &syncDBInterface]() { - std::this_thread::sleep_for(std::chrono::milliseconds(1)); - syncer->Close(true); - }); - closeThread.join(); - writeThread.join(); - } - syncer = nullptr; - std::this_thread::sleep_for(std::chrono::seconds(1)); - RuntimeContext::GetInstance()->SetCommunicatorAggregator(nullptr); - delete syncDBInterface; + ASSERT_NO_FATAL_FAILURE(SyncLifeTest002()); } /** @@ -934,25 +1033,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, SyncLifeTest002, TestSize.Level3) */ HWTEST_F(DistributedDBMockSyncModuleTest, SyncLifeTest003, TestSize.Level3) { - VirtualCommunicatorAggregator *virtualCommunicatorAggregator = new VirtualCommunicatorAggregator(); - RuntimeContext::GetInstance()->SetCommunicatorAggregator(virtualCommunicatorAggregator); - TestInterface *syncDBInterface = new TestInterface(); - const std::string DEVICE_B = "deviceB"; - std::string userId = "userId_0"; - std::string storeId = "storeId_0"; - std::string appId = "appId_0"; - std::string identifier = KvStoreDelegateManager::GetKvStoreIdentifier(userId, appId, storeId); - std::vector identifierVec(identifier.begin(), identifier.end()); - syncDBInterface->TestSetIdentifier(identifierVec); - syncDBInterface->Initialize(); - virtualCommunicatorAggregator->OnlineDevice(DEVICE_B); - syncDBInterface->TestLocalChange(); - virtualCommunicatorAggregator->OfflineDevice(DEVICE_B); - syncDBInterface->Close(); - RefObject::KillAndDecObjRef(syncDBInterface); - RuntimeContext::GetInstance()->StopTaskPool(); - std::this_thread::sleep_for(std::chrono::seconds(1)); - RuntimeContext::GetInstance()->SetCommunicatorAggregator(nullptr); + ASSERT_NO_FATAL_FAILURE(SyncLifeTest003()); } /** @@ -979,8 +1060,8 @@ HWTEST_F(DistributedDBMockSyncModuleTest, SyncLifeTest004, TestSize.Level3) syncer->EnableAutoSync(true); incRefCount = 0; syncer->RemoteDataChanged(""); - EXPECT_EQ(incRefCount, 1); // refCount is 1 std::this_thread::sleep_for(std::chrono::seconds(1)); + EXPECT_EQ(incRefCount, 2); // refCount is 2 syncer = nullptr; RuntimeContext::GetInstance()->SetCommunicatorAggregator(nullptr); delete syncDBInterface; @@ -1431,10 +1512,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, MockRemoteQuery001, TestSize.Level3) */ HWTEST_F(DistributedDBMockSyncModuleTest, MockRemoteQuery002, TestSize.Level3) { - MockRemoteExecutor *executor = new (std::nothrow) MockRemoteExecutor(); - ASSERT_NE(executor, nullptr); - executor->CallResponseFailed(0, 0, 0, "DEVICE"); - RefObject::KillAndDecObjRef(executor); + ASSERT_NO_FATAL_FAILURE(MockRemoteQuery002()); } /** @@ -1456,6 +1534,62 @@ HWTEST_F(DistributedDBMockSyncModuleTest, SyncTaskContextCheck001, TestSize.Leve EXPECT_EQ(syncTaskContext.CallIsCurrentSyncTaskCanBeSkipped(), true); } +/** + * @tc.name: SyncTaskContextCheck002 + * @tc.desc: test context check task can be skipped in push mode. + * @tc.type: FUNC + * @tc.require: AR000CCPOM + * @tc.author: zhangqiquan + */ +HWTEST_F(DistributedDBMockSyncModuleTest, SyncTaskContextCheck002, TestSize.Level1) +{ + /** + * @tc.steps: step1. create context and operation + */ + auto syncTaskContext = new(std::nothrow) MockSyncTaskContext(); + ASSERT_NE(syncTaskContext, nullptr); + auto operation = new SyncOperation(1u, {}, static_cast(SyncModeType::QUERY_PUSH), nullptr, false); + ASSERT_NE(operation, nullptr); + QuerySyncObject querySyncObject; + operation->SetQuery(querySyncObject); + syncTaskContext->SetSyncOperation(operation); + syncTaskContext->SetLastFullSyncTaskStatus(SyncOperation::Status::OP_FAILED); + syncTaskContext->CallSetSyncMode(static_cast(SyncModeType::QUERY_PUSH)); + EXPECT_CALL(*syncTaskContext, IsTargetQueueEmpty()).WillRepeatedly(Return(false)); + + const int loopCount = 1000; + /** + * @tc.steps: step2. loop 1000 times for writing data into lastQuerySyncTaskStatusMap_ async + */ + std::thread writeThread([&syncTaskContext]() { + for (int i = 0; i < loopCount; ++i) { + syncTaskContext->SaveLastPushTaskExecStatus(static_cast(SyncOperation::Status::OP_FAILED)); + } + }); + /** + * @tc.steps: step3. loop 100000 times for clear lastQuerySyncTaskStatusMap_ async + */ + std::thread clearThread([&syncTaskContext]() { + for (int i = 0; i < 100000; ++i) { // loop 100000 times + syncTaskContext->ResetLastPushTaskStatus(); + } + }); + /** + * @tc.steps: step4. loop 1000 times for read data from lastQuerySyncTaskStatusMap_ async + */ + std::thread readThread([&syncTaskContext]() { + for (int i = 0; i < loopCount; ++i) { + EXPECT_EQ(syncTaskContext->CallIsCurrentSyncTaskCanBeSkipped(), false); + } + }); + writeThread.join(); + clearThread.join(); + readThread.join(); + RefObject::KillAndDecObjRef(operation); + syncTaskContext->SetSyncOperation(nullptr); + RefObject::KillAndDecObjRef(syncTaskContext); +} + #ifdef RUN_AS_ROOT /** * @tc.name: TimeChangeListenerTest001 @@ -1531,9 +1665,52 @@ HWTEST_F(DistributedDBMockSyncModuleTest, TimeChangeListenerTest002, TestSize.Le */ HWTEST_F(DistributedDBMockSyncModuleTest, SyncerCheck001, TestSize.Level1) { + ASSERT_NO_FATAL_FAILURE(SyncerCheck001()); +} + +/** + * @tc.name: SyncerCheck002 + * @tc.desc: Test syncer call get timestamp with close and open. + * @tc.type: FUNC + * @tc.require: AR000CCPOM + * @tc.author: zhangqiquan + */ +HWTEST_F(DistributedDBMockSyncModuleTest, SyncerCheck002, TestSize.Level1) +{ + /** + * @tc.steps: step1. create context and syncer + */ std::shared_ptr syncer = std::make_shared(); - syncer->SetSyncRetry(true); + auto virtualCommunicatorAggregator = new(std::nothrow) VirtualCommunicatorAggregator(); + ASSERT_NE(virtualCommunicatorAggregator, nullptr); + auto syncDBInterface = new VirtualSingleVerSyncDBInterface(); + ASSERT_NE(syncDBInterface, nullptr); + std::vector identifier(COMM_LABEL_LENGTH, 1u); + syncDBInterface->SetIdentifier(identifier); + RuntimeContext::GetInstance()->SetCommunicatorAggregator(virtualCommunicatorAggregator); + /** + * @tc.steps: step2. get timestamp by syncer over and over again + */ + std::atomic finish = false; + std::thread t([&finish, &syncer]() { + while (!finish) { + (void) syncer->GetTimestamp(); + } + }); + /** + * @tc.steps: step3. re init syncer over and over again + * @tc.expected: step3. dont crash here. + */ + for (int i = 0; i < 100; ++i) { // loop 100 times + syncer->Initialize(syncDBInterface, false); + syncer->Close(true); + } + finish = true; + t.join(); + delete syncDBInterface; syncer = nullptr; + RuntimeContext::GetInstance()->SetCommunicatorAggregator(nullptr); + RuntimeContext::GetInstance()->StopTaskPool(); } /** @@ -1562,24 +1739,5 @@ HWTEST_F(DistributedDBMockSyncModuleTest, SessionId001, TestSize.Level1) */ HWTEST_F(DistributedDBMockSyncModuleTest, TimeSync001, TestSize.Level1) { - auto *communicator = new(std::nothrow) MockCommunicator(); - ASSERT_NE(communicator, nullptr); - auto *storage = new(std::nothrow) VirtualSingleVerSyncDBInterface(); - ASSERT_NE(storage, nullptr); - std::shared_ptr metadata = std::make_shared(); - - EXPECT_CALL(*communicator, SendMessage(_, _, _, _)).WillRepeatedly(Return(DB_ERROR)); - const int loopCount = 100; - const int timeDriverMs = 100; - for (int i = 0; i < loopCount; ++i) { - MockTimeSync timeSync; - timeSync.Initialize(communicator, metadata, storage, "DEVICES_A"); - timeSync.ModifyTimer(timeDriverMs); - std::this_thread::sleep_for(std::chrono::milliseconds(timeDriverMs)); - timeSync.Close(); - } - std::this_thread::sleep_for(std::chrono::seconds(1)); - metadata = nullptr; - delete storage; - delete communicator; + ASSERT_NO_FATAL_FAILURE(TimeSync001()); } \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_relational_multi_user_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_relational_multi_user_test.cpp index e8824554..15917ba4 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_relational_multi_user_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_relational_multi_user_test.cpp @@ -878,7 +878,7 @@ HWTEST_F(DistributedDBRelationalMultiUserTest, RdbMultiUser010, TestSize.Level1) }); /** * @tc.steps: step2. openstore1 in dual tuple sync mode - * @tc.expected: step2. it should be activity finally + * @tc.expected: step2. it should be activated finally */ OpenStore1(true); /** @@ -913,4 +913,61 @@ HWTEST_F(DistributedDBRelationalMultiUserTest, RdbMultiUser011, TestSize.Level1) EXPECT_EQ(rdbDeletegatePtr, nullptr); CloseStore(); } +} + +/** + * @tc.name: multi user 012 + * @tc.desc: test dont check sync active when open store with normal store + * @tc.type: FUNC + * @tc.require: AR000GK58G + * @tc.author: zhangqiquan + */ +HWTEST_F(DistributedDBRelationalMultiUserTest, RdbMultiUser012, TestSize.Level1) +{ + uint32_t callCount = 0u; + /** + * @tc.steps: step1. set SyncActivationCheckCallback and record call count + */ + RuntimeConfig::SetSyncActivationCheckCallback([&callCount] (const std::string &userId, const std::string &appId, + const std::string &storeId) -> bool { + callCount++; + return true; + }); + /** + * @tc.steps: step2. openStore in no dual tuple sync mode + * @tc.expected: step2. it should be activated finally, and callCount should be zero + */ + OpenStore1(false); + EXPECT_EQ(callCount, 0u); + CloseStore(); +} + +/** + * @tc.name: multi user 013 + * @tc.desc: test dont check sync active when open store with normal store + * @tc.type: FUNC + * @tc.require: AR000GK58G + * @tc.author: zhangqiquan + */ +HWTEST_F(DistributedDBRelationalMultiUserTest, RdbMultiUser013, TestSize.Level1) +{ + uint32_t callCount = 0u; + /** + * @tc.steps: step1. set SyncActivationCheckCallback and record call count + */ + RuntimeConfig::SetSyncActivationCheckCallback([&callCount] (const std::string &userId, const std::string &appId, + const std::string &storeId) -> bool { + callCount++; + return true; + }); + /** + * @tc.steps: step2. openStore in dual tuple sync mode + * @tc.expected: step2. it should not be activated finally, and callCount should be 2 + */ + OpenStore1(true); + EXPECT_EQ(callCount, 2u); + callCount = 0u; + EXPECT_EQ(g_rdbDelegatePtr1->RemoveDeviceData("DEVICE"), OK); + EXPECT_EQ(callCount, 0u); + CloseStore(); } \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_relational_ver_p2p_sync_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_relational_ver_p2p_sync_test.cpp index 1ab5d57c..6ba4b686 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_relational_ver_p2p_sync_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_relational_ver_p2p_sync_test.cpp @@ -1082,6 +1082,7 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, NormalSync008, TestSize.Level0) std::vector targetData; g_deviceB->GetAllSyncData(g_tableName, targetData); ASSERT_EQ(targetData.size(), 0u); + EXPECT_EQ(sqlite3_close_v2(db), SQLITE_OK); } /** @@ -1204,94 +1205,6 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, AutoLaunchSync001, TestSize.Leve EXPECT_EQ(currentStatus, AutoLaunchStatus::WRITE_CLOSED); } -/** -* @tc.name: AutoLaunchSyncAfterRekey_001 -* @tc.desc: Test auto launch sync ok after rekey. -* @tc.type: FUNC -* @tc.require: AR000H68LL -* @tc.author: lidongwei -*/ -#ifndef OMIT_ENCRYPT -HWTEST_F(DistributedDBRelationalVerP2PSyncTest, AutoLaunchSyncAfterRekey_001, TestSize.Level3) -{ - /** - * @tc.steps: step1. open rdb store, create distribute table and insert data - */ - std::map dataMap; - PrepareVirtualEnvironment(dataMap, {g_deviceB}); - - /** - * @tc.steps: step2. set auto launch callBack - */ - AutoLaunchParam encryptedParam { USER_ID, APP_ID, STORE_ID_1, AutoLaunchOption {}, nullptr, g_dbDir }; - encryptedParam.option.isEncryptedDb = true; - encryptedParam.option.cipher = CipherType::DEFAULT; - encryptedParam.option.passwd = g_correctPasswd; - encryptedParam.option.iterateTimes = DEFAULT_ITER; - AutoLaunchRequestCallback callback = [&encryptedParam](const std::string &identifier, AutoLaunchParam ¶m) { - if (g_id != identifier) { - return false; - } - param = encryptedParam; - return true; - }; - g_mgr.SetAutoLaunchRequestCallback(callback); - /** - * @tc.steps: step3. close store ensure communicator has closed - */ - g_mgr.CloseStore(g_rdbDelegatePtr); - g_rdbDelegatePtr = nullptr; - /** - * @tc.steps: step4. RunCommunicatorLackCallback to autolaunch store - */ - LabelType labelType(g_id.begin(), g_id.end()); - g_communicatorAggregator->RunCommunicatorLackCallback(labelType); - std::this_thread::sleep_for(std::chrono::seconds(1)); - - /** - * @tc.steps: step5. Rekey - */ - sqlite3 *db = nullptr; - EXPECT_EQ(GetDB(db), SQLITE_OK); - std::thread t1([&db] { - std::string sql = "PARGMA rekey=" + REKEY_KEY; - EXPECT_EQ(sqlite3_rekey(db, REKEY_KEY.data(), REKEY_KEY.size()), SQLITE_OK); - }); - t1.join(); - g_isAfterRekey = true; - - /** - * @tc.steps: step6. Call sync expect sync failed - */ - Query query = Query::Select(g_tableName); - EXPECT_EQ(g_deviceB->GenericVirtualDevice::Sync(SYNC_MODE_PUSH_ONLY, query, true), E_OK); - size_t count = 0; - GetCount(db, "SELECT count(*) FROM sqlite_master WHERE name='" + GetDeviceTableName(g_tableName) + "';", count); - EXPECT_EQ(count, 0u); - - /** - * @tc.steps: step7. Set callback. - */ - encryptedParam.option.passwd = g_rekeyPasswd; - g_mgr.SetAutoLaunchRequestCallback(callback); - g_communicatorAggregator->RunCommunicatorLackCallback(labelType); - std::this_thread::sleep_for(std::chrono::seconds(2)); - - /** - * @tc.steps: step8. Call sync expect sync success - */ - EXPECT_EQ(g_deviceB->GenericVirtualDevice::Sync(SYNC_MODE_PUSH_ONLY, query, true), E_OK); - GetCount(db, "SELECT count(*) FROM sqlite_master WHERE name='" + GetDeviceTableName(g_tableName) + "';", count); - EXPECT_EQ(count, 1u); - GetSyncData(db, dataMap, g_tableName, g_fieldInfoList); - EXPECT_EQ(dataMap.size(), 3u); - OpenStore(); - std::this_thread::sleep_for(std::chrono::minutes(1)); - sqlite3_close(db); - db = nullptr; -} -#endif - /** * @tc.name: AutoLaunchSync 002 * @tc.desc: Test rdb autoLaunch failed when callback return false. @@ -2381,4 +2294,164 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, EncryptedAlgoUpgrade001, TestSiz g_deviceB->GenericVirtualDevice::Sync(DistributedDB::SYNC_MODE_PULL_ONLY, query, true); CheckVirtualData(dataMap); } + +#ifndef OMIT_ENCRYPT +/** +* @tc.name: AutoLaunchSyncAfterRekey_001 +* @tc.desc: Test auto launch sync ok after rekey. +* @tc.type: FUNC +* @tc.require: AR000H68LL +* @tc.author: lidongwei +*/ +HWTEST_F(DistributedDBRelationalVerP2PSyncTest, AutoLaunchSyncAfterRekey_001, TestSize.Level3) +{ + /** + * @tc.steps: step1. open rdb store, create distribute table and insert data + */ + std::map dataMap; + PrepareVirtualEnvironment(dataMap, {g_deviceB}); + + /** + * @tc.steps: step2. set auto launch callBack + */ + AutoLaunchParam encryptedParam { USER_ID, APP_ID, STORE_ID_1, AutoLaunchOption {}, nullptr, g_dbDir }; + encryptedParam.option.isEncryptedDb = true; + encryptedParam.option.cipher = CipherType::DEFAULT; + encryptedParam.option.passwd = g_correctPasswd; + encryptedParam.option.iterateTimes = DEFAULT_ITER; + AutoLaunchRequestCallback callback = [&encryptedParam](const std::string &identifier, AutoLaunchParam ¶m) { + if (g_id != identifier) { + return false; + } + param = encryptedParam; + return true; + }; + g_mgr.SetAutoLaunchRequestCallback(callback); + /** + * @tc.steps: step3. close store ensure communicator has closed + */ + g_mgr.CloseStore(g_rdbDelegatePtr); + g_rdbDelegatePtr = nullptr; + /** + * @tc.steps: step4. RunCommunicatorLackCallback to autolaunch store + */ + LabelType labelType(g_id.begin(), g_id.end()); + g_communicatorAggregator->RunCommunicatorLackCallback(labelType); + std::this_thread::sleep_for(std::chrono::seconds(1)); + + /** + * @tc.steps: step5. Rekey + */ + sqlite3 *db = nullptr; + EXPECT_EQ(GetDB(db), SQLITE_OK); + std::thread t1([&db] { + std::string sql = "PARGMA rekey=" + REKEY_KEY; + EXPECT_EQ(sqlite3_rekey(db, REKEY_KEY.data(), REKEY_KEY.size()), SQLITE_OK); + }); + t1.join(); + g_isAfterRekey = true; + + /** + * @tc.steps: step6. Call sync expect sync failed + */ + Query query = Query::Select(g_tableName); + EXPECT_EQ(g_deviceB->GenericVirtualDevice::Sync(SYNC_MODE_PUSH_ONLY, query, true), E_OK); + size_t count = 0; + GetCount(db, "SELECT count(*) FROM sqlite_master WHERE name='" + GetDeviceTableName(g_tableName) + "';", count); + EXPECT_EQ(count, 0u); + + /** + * @tc.steps: step7. Set callback. + */ + encryptedParam.option.passwd = g_rekeyPasswd; + g_mgr.SetAutoLaunchRequestCallback(callback); + g_communicatorAggregator->RunCommunicatorLackCallback(labelType); + std::this_thread::sleep_for(std::chrono::seconds(2)); + + /** + * @tc.steps: step8. Call sync expect sync success + */ + EXPECT_EQ(g_deviceB->GenericVirtualDevice::Sync(SYNC_MODE_PUSH_ONLY, query, true), E_OK); + GetCount(db, "SELECT count(*) FROM sqlite_master WHERE name='" + GetDeviceTableName(g_tableName) + "';", count); + EXPECT_EQ(count, 1u); + GetSyncData(db, dataMap, g_tableName, g_fieldInfoList); + EXPECT_EQ(dataMap.size(), 3u); + OpenStore(); + std::this_thread::sleep_for(std::chrono::minutes(1)); + sqlite3_close(db); + db = nullptr; +} + +/** +* @tc.name: AutoLaunchSyncAfterRekey_002 +* @tc.desc: Test auto launch close check after rekey. +* @tc.type: FUNC +* @tc.require: AR000H68LL +* @tc.author: zhangqiquan +*/ +HWTEST_F(DistributedDBRelationalVerP2PSyncTest, AutoLaunchSyncAfterRekey_002, TestSize.Level3) +{ + /** + * @tc.steps: step1. open rdb store, create distribute table and insert data + */ + std::map dataMap; + PrepareVirtualEnvironment(dataMap, {g_deviceB}); + /** + * @tc.steps: step2. set auto launch callBack + */ + AutoLaunchParam encryptedParam { USER_ID, APP_ID, STORE_ID_1, AutoLaunchOption {}, nullptr, g_dbDir }; + encryptedParam.option.isEncryptedDb = true; + encryptedParam.option.cipher = CipherType::DEFAULT; + encryptedParam.option.passwd = g_correctPasswd; + encryptedParam.option.iterateTimes = DEFAULT_ITER; + AutoLaunchRequestCallback callback = [&encryptedParam](const std::string &identifier, AutoLaunchParam ¶m) { + param = encryptedParam; + return true; + }; + RelationalStoreManager::SetAutoLaunchRequestCallback(callback); + /** + * @tc.steps: step3. close store ensure communicator has closed + */ + g_mgr.CloseStore(g_rdbDelegatePtr); + g_rdbDelegatePtr = nullptr; + /** + * @tc.steps: step4. RunCommunicatorLackCallback to autolaunch store + */ + LabelType labelType(g_id.begin(), g_id.end()); + g_communicatorAggregator->RunCommunicatorLackCallback(labelType); + std::this_thread::sleep_for(std::chrono::seconds(2)); // wait 2s for auto launch + /** + * @tc.steps: step5. Rekey + */ + sqlite3 *db = nullptr; + EXPECT_EQ(GetDB(db), SQLITE_OK); + std::string sql = "PARGMA rekey=" + REKEY_KEY; + EXPECT_EQ(sqlite3_rekey(db, REKEY_KEY.data(), REKEY_KEY.size()), SQLITE_OK); + g_isAfterRekey = true; + + RelationalDBProperties properties; + properties.SetStringProp(DBProperties::USER_ID, USER_ID); + properties.SetStringProp(DBProperties::APP_ID, APP_ID); + properties.SetStringProp(DBProperties::STORE_ID, STORE_ID_1); + const string &id = RelationalStoreManager::GetRelationalStoreIdentifier(USER_ID, APP_ID, STORE_ID_1); + properties.SetStringProp(DBProperties::IDENTIFIER_DATA, id); + RuntimeContext::GetInstance()->CloseAutoLaunchConnection(DBType::DB_RELATION, properties); + + encryptedParam.option.passwd = g_rekeyPasswd; + RelationalStoreManager::SetAutoLaunchRequestCallback(callback); + g_communicatorAggregator->RunCommunicatorLackCallback(labelType); + std::this_thread::sleep_for(std::chrono::seconds(2)); // wait 2s for auto launch + + Query query = Query::Select(g_tableName); + EXPECT_EQ(g_deviceB->GenericVirtualDevice::Sync(SYNC_MODE_PUSH_ONLY, query, true), E_OK); + size_t count = 0; + GetCount(db, "SELECT count(*) FROM sqlite_master WHERE name='" + GetDeviceTableName(g_tableName) + "';", count); + EXPECT_EQ(count, 0u); + + OpenStore(); + std::this_thread::sleep_for(std::chrono::minutes(1)); + sqlite3_close(db); + db = nullptr; +} +#endif #endif \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_multi_user_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_multi_user_test.cpp index 515150a2..3676e58e 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_multi_user_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_multi_user_test.cpp @@ -795,7 +795,7 @@ HWTEST_F(DistributedDBSingleVerMultiUserTest, MultiUser011, TestSize.Level1) }); /** * @tc.steps: step2. openstore1 in dual tuple sync mode - * @tc.expected: step2. it should be activity finally + * @tc.expected: step2. it should be activated finally */ OpenStore1(true); /** @@ -843,4 +843,61 @@ HWTEST_F(DistributedDBSingleVerMultiUserTest, MultiUser012, TestSize.Level1) std::this_thread::sleep_for(std::chrono::milliseconds(WAIT_3_SECONDS)); subThread.join(); CloseStore(); +} + +/** + * @tc.name: MultiUser013 + * @tc.desc: test dont check sync active when open store with normal store + * @tc.type: FUNC + * @tc.require: AR000E8S2T + * @tc.author: zhangqiquan + */ +HWTEST_F(DistributedDBSingleVerMultiUserTest, MultiUser013, TestSize.Level1) +{ + uint32_t callCount = 0u; + /** + * @tc.steps: step1. set SyncActivationCheckCallback and record call count + */ + KvStoreDelegateManager::SetSyncActivationCheckCallback( + [&callCount] (const std::string &userId, const std::string &appId, const std::string &storeId) -> bool { + callCount++; + return true; + }); + /** + * @tc.steps: step2. openStore in no dual tuple sync mode + * @tc.expected: step2. it should be activated finally, and callCount should be zero + */ + OpenStore1(false); + EXPECT_EQ(callCount, 0u); + CloseStore(); +} + +/** + * @tc.name: MultiUser014 + * @tc.desc: test active callback call count + * @tc.type: FUNC + * @tc.require: AR000E8S2T + * @tc.author: zhangqiquan + */ +HWTEST_F(DistributedDBSingleVerMultiUserTest, MultiUser014, TestSize.Level1) +{ + uint32_t callCount = 0u; + /** + * @tc.steps: step1. set SyncActivationCheckCallback and record call count + */ + KvStoreDelegateManager::SetSyncActivationCheckCallback( + [&callCount] (const std::string &userId, const std::string &appId, const std::string &storeId) -> bool { + callCount++; + return false; + }); + /** + * @tc.steps: step2. openStore in dual tuple sync mode + * @tc.expected: step2. it should not be activated finally, and callCount should be 2 + */ + OpenStore1(true); + EXPECT_EQ(callCount, 2u); // 2 is call count + callCount = 0u; + EXPECT_EQ(g_kvDelegatePtr1->RemoveDeviceData(), OK); + EXPECT_EQ(callCount, 0u); + CloseStore(); } \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_complex_sync_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_complex_sync_test.cpp index dfa5b3c6..e8887801 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_complex_sync_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_complex_sync_test.cpp @@ -23,6 +23,7 @@ #include "distributeddb_tools_unit_test.h" #include "kv_store_nb_delegate.h" #include "kv_virtual_device.h" +#include "mock_sync_task_context.h" #include "platform_specific.h" #include "single_ver_data_sync.h" #include "single_ver_kv_sync_task_context.h" @@ -125,6 +126,58 @@ namespace { EXPECT_TRUE(resultvalue == value); } } + + void DataSync005() + { + ASSERT_NE(g_communicatorAggregator, nullptr); + SingleVerDataSync *dataSync = new (std::nothrow) SingleVerDataSync(); + ASSERT_TRUE(dataSync != nullptr); + dataSync->SendSaveDataNotifyPacket(nullptr, 0, 0, 0, TIME_SYNC_MESSAGE); + EXPECT_EQ(g_communicatorAggregator->GetOnlineDevices().size(), 3u); // 3 online dev + delete dataSync; + } + + void DataSync008() + { + SingleVerDataSync *dataSync = new (std::nothrow) SingleVerDataSync(); + ASSERT_TRUE(dataSync != nullptr); + auto context = new (std::nothrow) MockSyncTaskContext(); + dataSync->PutDataMsg(nullptr); + bool isNeedHandle = false; + bool isContinue = false; + EXPECT_EQ(dataSync->MoveNextDataMsg(context, isNeedHandle, isContinue), nullptr); + EXPECT_EQ(isNeedHandle, false); + EXPECT_EQ(isContinue, false); + delete dataSync; + delete context; + } + + void ReSetWaterDogTest001() + { + /** + * @tc.steps: step1. put 10 key/value + * @tc.expected: step1, put return OK. + */ + for (int i = 0; i < 5; i++) { // put 5 key + Key key = DistributedDBToolsUnitTest::GetRandPrefixKey({'a', 'b'}, 1024); // rand num 1024 for test + Value value; + DistributedDBToolsUnitTest::GetRandomKeyValue(value, 10 * 50 * 1024u); // 10 * 50 * 1024 = 500k + EXPECT_EQ(g_kvDelegatePtr->Put(key, value), OK); + } + /** + * @tc.steps: step2. SetDeviceMtuSize + * @tc.expected: step2, return OK. + */ + g_communicatorAggregator->SetDeviceMtuSize(DEVICE_A, 50 * 1024u); // 50 * 1024u = 50k + g_communicatorAggregator->SetDeviceMtuSize(DEVICE_B, 50 * 1024u); // 50 * 1024u = 50k + /** + * @tc.steps: step3. deviceA,deviceB sync to each other at same time + * @tc.expected: step3. sync should return OK. + */ + EXPECT_EQ(g_deviceB->Sync(DistributedDB::SYNC_MODE_PULL_ONLY, true), E_OK); + g_communicatorAggregator->SetDeviceMtuSize(DEVICE_A, 5 * 1024u * 1024u); // 5 * 1024u * 1024u = 5m + g_communicatorAggregator->SetDeviceMtuSize(DEVICE_B, 5 * 1024u * 1024u); // 5 * 1024u * 1024u = 5m + } } class DistributedDBSingleVerP2PComplexSyncTest : public testing::Test { @@ -977,10 +1030,7 @@ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, DataSync004, TestSize.Level1) */ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, DataSync005, TestSize.Level1) { - SingleVerDataSync *dataSync = new (std::nothrow) SingleVerDataSync(); - ASSERT_TRUE(dataSync != nullptr); - dataSync->SendSaveDataNotifyPacket(nullptr, 0, 0, 0, TIME_SYNC_MESSAGE); - delete dataSync; + ASSERT_NO_FATAL_FAILURE(DataSync005()); } /** @@ -1040,10 +1090,7 @@ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, DataSync007, TestSize.Level1) */ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, DataSync008, TestSize.Level1) { - SingleVerDataSync *dataSync = new (std::nothrow) SingleVerDataSync(); - ASSERT_TRUE(dataSync != nullptr); - dataSync->PutDataMsg(nullptr); - delete dataSync; + ASSERT_NO_FATAL_FAILURE(DataSync008()); } /** @@ -1240,37 +1287,68 @@ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, SyncRetry004, TestSize.Level3 } /** - * @tc.name: ReSetWatchDogTest001 - * @tc.desc: trigger resetWatchDog while pull + * @tc.name: SyncRetry005 + * @tc.desc: use sync retry sync use pull by compress * @tc.type: FUNC * @tc.require: AR000CKRTD AR000CQE0E - * @tc.author: zhuwentao + * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, ReSetWaterDogTest001, TestSize.Level3) +HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, SyncRetry005, TestSize.Level3) { + if (g_kvDelegatePtr != nullptr) { + ASSERT_EQ(g_mgr.CloseKvStore(g_kvDelegatePtr), OK); + g_kvDelegatePtr = nullptr; + } /** - * @tc.steps: step1. put 10 key/value - * @tc.expected: step1, put return OK. + * @tc.steps: step1. open db use Compress + * @tc.expected: step1, Pragma return OK. */ - for (int i = 0; i < 5; i++) { - Key key = DistributedDBToolsUnitTest::GetRandPrefixKey({'a', 'b'}, 1024); // rand num 1024 for test - Value value; - DistributedDBToolsUnitTest::GetRandomKeyValue(value, 10 * 50 * 1024u); - EXPECT_EQ(g_kvDelegatePtr->Put(key, value), OK); - } + KvStoreNbDelegate::Option option; + option.isNeedCompressOnSync = true; + g_mgr.GetKvStore(STORE_ID, option, g_kvDelegateCallback); + ASSERT_TRUE(g_kvDelegateStatus == OK); + ASSERT_TRUE(g_kvDelegatePtr != nullptr); + + g_communicatorAggregator->SetDropMessageTypeByDevice(DEVICE_B, DATA_SYNC_MESSAGE); + std::vector devices; + devices.push_back(g_deviceB->GetDeviceId()); + + /** + * @tc.steps: step2. set sync retry + * @tc.expected: step2, Pragma return OK. + */ + int pragmaData = 1; + PragmaData input = static_cast(&pragmaData); + EXPECT_TRUE(g_kvDelegatePtr->Pragma(SET_SYNC_RETRY, input) == OK); + /** - * @tc.steps: step1. SetDeviceMtuSize - * @tc.expected: step1, return OK. + * @tc.steps: step3. deviceA call sync and wait + * @tc.expected: step3. sync should return OK. */ - g_communicatorAggregator->SetDeviceMtuSize(DEVICE_A, 50 * 1024u); // 4k - g_communicatorAggregator->SetDeviceMtuSize(DEVICE_B, 50 * 1024u); // 4k + std::map result; + ASSERT_TRUE(g_tool.SyncTest(g_kvDelegatePtr, devices, SYNC_MODE_PULL_ONLY, result) == OK); + /** - * @tc.steps: step2. deviceA,deviceB sync to each other at same time - * @tc.expected: step2. sync should return OK. + * @tc.expected: step4. onComplete should be called, and status is time_out */ - g_deviceB->Sync(DistributedDB::SYNC_MODE_PULL_ONLY, true); - g_communicatorAggregator->SetDeviceMtuSize(DEVICE_A, 5 * 1024u * 1024u); // 4k - g_communicatorAggregator->SetDeviceMtuSize(DEVICE_B, 5 * 1024u * 1024u); // 4k + ASSERT_TRUE(result.size() == devices.size()); + for (const auto &pair : result) { + LOGD("dev %s, status %d", pair.first.c_str(), pair.second); + EXPECT_EQ(pair.second, OK); + } + g_communicatorAggregator->SetDropMessageTypeByDevice(DEVICE_B, UNKNOW_MESSAGE); +} + +/** + * @tc.name: ReSetWatchDogTest001 + * @tc.desc: trigger resetWatchDog while pull + * @tc.type: FUNC + * @tc.require: AR000CKRTD AR000CQE0E + * @tc.author: zhuwentao + */ +HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, ReSetWaterDogTest001, TestSize.Level3) +{ + ASSERT_NO_FATAL_FAILURE(ReSetWaterDogTest001()); } /** @@ -1865,4 +1943,54 @@ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, InterceptDataFail001, TestSiz } VirtualDataItem item; EXPECT_EQ(g_deviceB->GetData(key, item), -E_NOT_FOUND); +} + +/** + * @tc.name: UpdateKey001 + * @tc.desc: test update key can effect local data and sync data, without delete data + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangqiquan + */ +HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, UpdateKey001, TestSize.Level1) +{ + /** + * @tc.steps: step1. device A set sync data (k1, v1) local data (k2, v2) (k3, v3) and delete (k4, v4) + * @tc.expected: step1. put data return ok + */ + Key k1 = {'k', '1'}; + Value v1 = {'v', '1'}; + g_deviceB->PutData(k1, v1, 1, 0); + ASSERT_EQ(g_deviceB->Sync(SyncMode::SYNC_MODE_PUSH_ONLY, true), E_OK); + Value actualValue; + EXPECT_EQ(g_kvDelegatePtr->Get(k1, actualValue), OK); + EXPECT_EQ(v1, actualValue); + Key k2 = {'k', '2'}; + Value v2 = {'v', '2'}; + Key k3 = {'k', '3'}; + Value v3 = {'v', '3'}; + Key k4 = {'k', '4'}; + Value v4 = {'v', '4'}; + EXPECT_EQ(g_kvDelegatePtr->Put(k2, v2), OK); + EXPECT_EQ(g_kvDelegatePtr->Put(k3, v3), OK); + EXPECT_EQ(g_kvDelegatePtr->Put(k4, v4), OK); + EXPECT_EQ(g_kvDelegatePtr->Delete(k4), OK); + /** + * @tc.steps: step2. device A update key and set + * @tc.expected: step2. put data return ok + */ + DBStatus status = g_kvDelegatePtr->UpdateKey([](const Key &originKey, Key &newKey) { + newKey = originKey; + newKey.push_back('0'); + }); + EXPECT_EQ(status, OK); + k1.push_back('0'); + k2.push_back('0'); + k3.push_back('0'); + EXPECT_EQ(g_kvDelegatePtr->Get(k1, actualValue), OK); + EXPECT_EQ(v1, actualValue); + EXPECT_EQ(g_kvDelegatePtr->Get(k2, actualValue), OK); + EXPECT_EQ(v2, actualValue); + EXPECT_EQ(g_kvDelegatePtr->Get(k3, actualValue), OK); + EXPECT_EQ(v3, actualValue); } \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_permission_sync_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_permission_sync_test.cpp index 8c498b1d..d9810710 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_permission_sync_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_permission_sync_test.cpp @@ -771,4 +771,52 @@ HWTEST_F(DistributedDBSingleVerP2PPermissionSyncTest, PermissionCheck009, TestSi } PermissionCheckCallbackV2 nullCallback; EXPECT_EQ(g_mgr.SetPermissionCheckCallback(nullCallback), OK); +} + +/** + * @tc.name: PermissionCheck010 + * @tc.desc: permission check cost lot of time and return false + * @tc.type: FUNC + * @tc.require: AR000D4876 + * @tc.author: zhangqiquan + */ +HWTEST_F(DistributedDBSingleVerP2PPermissionSyncTest, PermissionCheck010, TestSize.Level3) +{ + /** + * @tc.steps: step1. SetPermissionCheckCallback + * @tc.expected: step1. return OK. + */ + int count = 0; + auto permissionCheckCallback = [&count] (const std::string &userId, const std::string &appId, + const std::string &storeId, const std::string &deviceId, uint8_t flag) -> bool { + std::this_thread::sleep_for(std::chrono::seconds(1)); + count++; + LOGD("check permission %d", count); + return count > 1; + }; + EXPECT_EQ(g_mgr.SetPermissionCheckCallback(permissionCheckCallback), OK); + /** + * @tc.steps: step2. put (k1, v1) + * @tc.expected: step2. return OK. + */ + Key k1 = {'k', '1'}; + Value v1 = {'v', '1'}; + EXPECT_EQ(g_kvDelegatePtr->Put(k1, v1), OK); + /** + * @tc.steps: step3. sync to DEVICE_B twice + * @tc.expected: step3. return OK. + */ + std::vector devices; + devices.push_back(DEVICE_B); + EXPECT_TRUE(g_kvDelegatePtr->Sync(devices, SYNC_MODE_PUSH_ONLY, nullptr, false) == OK); + EXPECT_TRUE(g_kvDelegatePtr->Sync(devices, SYNC_MODE_PUSH_ONLY, nullptr, true) == OK); + /** + * @tc.steps: step4. (k1, v1) exist in DeviceB + * @tc.expected: step4. get return OK. + */ + VirtualDataItem actualValue; + EXPECT_EQ(g_deviceB->GetData(k1, actualValue), OK); + EXPECT_EQ(v1, actualValue.value); + PermissionCheckCallbackV2 nullCallback = nullptr; + EXPECT_EQ(g_mgr.SetPermissionCheckCallback(nullCallback), OK); } \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_query_sync_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_query_sync_test.cpp index 36e41216..4a928773 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_query_sync_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_query_sync_test.cpp @@ -895,6 +895,78 @@ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, GetQueryWaterMark002, TestSize. EXPECT_EQ(w1, w); } +/** + * @tc.name: GetQueryWaterMark 003 + * @tc.desc: check time offset after remove water mark + * @tc.type: FUNC + * @tc.require: + * @tc.author: lianhuix + */ +HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, GetQueryWaterMark003, TestSize.Level1) +{ + VirtualSingleVerSyncDBInterface storage; + Metadata meta; + + int errCode = meta.Initialize(&storage); + ASSERT_EQ(errCode, E_OK); + + const std::string DEVICE_B = "DEVICE_B"; + TimeOffset offset = 100; // 100: offset + meta.SaveTimeOffset(DEVICE_B, offset); + + WaterMark w1 = 2; // 2: watermark + meta.SavePeerWaterMark(DBCommon::TransferHashString(DEVICE_B), w1, false); + + TimeOffset offsetGot; + meta.GetTimeOffset(DEVICE_B, offsetGot); + EXPECT_EQ(offsetGot, offset); +} + +/** + * @tc.name: GetDeleteWaterMark001 + * @tc.desc: Test metaData save and get deleteWaterMark. + * @tc.type: FUNC + * @tc.require: AR000FN6G9 + * @tc.author: zhangqiquan + */ +HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, GetDeleteWaterMark001, TestSize.Level1) +{ + VirtualSingleVerSyncDBInterface storage; + Metadata meta; + + /** + * @tc.steps: step1. initialize meta with storage + * @tc.expected: step1. E_OK + */ + int errCode = meta.Initialize(&storage); + ASSERT_EQ(errCode, E_OK); + + /** + * @tc.steps: step2. set and get recv/send delete watermark + * @tc.expected: step2. set E_OK and get water mark is equal with last set + */ + const std::string device = "DEVICE"; + const WaterMark maxWaterMark = 1000u; + std::thread recvThread([&meta, &device, &maxWaterMark]() { + for (WaterMark expectRecv = 0u; expectRecv < maxWaterMark; ++expectRecv) { + EXPECT_EQ(meta.SetRecvDeleteSyncWaterMark(device, expectRecv), E_OK); + WaterMark actualRecv = 0u; + EXPECT_EQ(meta.GetRecvDeleteSyncWaterMark(device, actualRecv), E_OK); + EXPECT_EQ(actualRecv, expectRecv); + } + }); + std::thread sendThread([&meta, &device, &maxWaterMark]() { + for (WaterMark expectSend = 0u; expectSend < maxWaterMark; ++expectSend) { + EXPECT_EQ(meta.SetSendDeleteSyncWaterMark(device, expectSend), E_OK); + WaterMark actualSend = 0u; + EXPECT_EQ(meta.GetSendDeleteSyncWaterMark(device, actualSend), E_OK); + EXPECT_EQ(actualSend, expectSend); + } + }); + recvThread.join(); + sendThread.join(); +} + /** * @tc.name: ClearQueryWaterMark 001 * @tc.desc: Test metaData clear watermark function. @@ -1830,31 +1902,4 @@ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, AllPredicateQuerySync004, TestS EXPECT_TRUE(item == value); key.pop_back(); } -} - -/** - * @tc.name: GetQueryWaterMark 003 - * @tc.desc: check time offset after remove water mark - * @tc.type: FUNC - * @tc.require: - * @tc.author: lianhuix - */ -HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, GetQueryWaterMark003, TestSize.Level1) -{ - VirtualSingleVerSyncDBInterface storage; - Metadata meta; - - int errCode = meta.Initialize(&storage); - ASSERT_EQ(errCode, E_OK); - - const std::string DEVICE_B = "DEVICE_B"; - TimeOffset offset = 100; // 100: offset - meta.SaveTimeOffset(DEVICE_B, offset); - - WaterMark w1 = 2; // 2: watermark - meta.SavePeerWaterMark(DBCommon::TransferHashString(DEVICE_B), w1, false); - - TimeOffset offsetGot; - meta.GetTimeOffset(DEVICE_B, offsetGot); - EXPECT_EQ(offsetGot, offset); -} +} \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_subscribe_sync_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_subscribe_sync_test.cpp index cd6eb2ec..207e1469 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_subscribe_sync_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_subscribe_sync_test.cpp @@ -349,7 +349,7 @@ HWTEST_F(DistributedDBSingleVerP2PSubscribeSyncTest, ControlAckTest001, TestSize * @tc.require: AR000FN6G9 * @tc.author: zhuwentao */ -HWTEST_F(DistributedDBSingleVerP2PSubscribeSyncTest, subscribeManager001, TestSize.Level1) +HWTEST_F(DistributedDBSingleVerP2PSubscribeSyncTest, SubscribeManager001, TestSize.Level1) { SubscribeManager subManager; std::string device = "device_A"; @@ -420,7 +420,7 @@ HWTEST_F(DistributedDBSingleVerP2PSubscribeSyncTest, subscribeManager001, TestSi * @tc.require: AR000FN6G9 * @tc.author: zhuwentao */ -HWTEST_F(DistributedDBSingleVerP2PSubscribeSyncTest, subscribeManager002, TestSize.Level1) +HWTEST_F(DistributedDBSingleVerP2PSubscribeSyncTest, SubscribeManager002, TestSize.Level1) { SubscribeManager subManager; std::string device = "device_A"; @@ -476,7 +476,7 @@ ASSERT_TRUE(subscribeQueryId.size() == 4); * @tc.require: AR000FN6G9 * @tc.author: zhuwentao */ -HWTEST_F(DistributedDBSingleVerP2PSubscribeSyncTest, subscribeManager003, TestSize.Level1) +HWTEST_F(DistributedDBSingleVerP2PSubscribeSyncTest, SubscribeManager003, TestSize.Level1) { SubscribeManager subManager; std::string device = "device_"; @@ -526,7 +526,7 @@ HWTEST_F(DistributedDBSingleVerP2PSubscribeSyncTest, subscribeManager003, TestSi * @tc.require: AR000FN6G9 * @tc.author: zhuwentao */ -HWTEST_F(DistributedDBSingleVerP2PSubscribeSyncTest, subscribeManager004, TestSize.Level1) +HWTEST_F(DistributedDBSingleVerP2PSubscribeSyncTest, SubscribeManager004, TestSize.Level1) { SubscribeManager subManager; std::string device = "device_"; @@ -577,7 +577,7 @@ HWTEST_F(DistributedDBSingleVerP2PSubscribeSyncTest, subscribeManager004, TestSi * @tc.require: AR000FN6G9 * @tc.author: zhuwentao */ -HWTEST_F(DistributedDBSingleVerP2PSubscribeSyncTest, subscribeManager005, TestSize.Level1) +HWTEST_F(DistributedDBSingleVerP2PSubscribeSyncTest, SubscribeManager005, TestSize.Level1) { SubscribeManager subManager; std::vector subscribeQueries; @@ -647,7 +647,7 @@ HWTEST_F(DistributedDBSingleVerP2PSubscribeSyncTest, subscribeManager005, TestSi * @tc.require: * @tc.author: zhangshijie */ -HWTEST_F(DistributedDBSingleVerP2PSubscribeSyncTest, subscribeManager006, TestSize.Level1) +HWTEST_F(DistributedDBSingleVerP2PSubscribeSyncTest, SubscribeManager006, TestSize.Level1) { /** * @tc.steps: step1. active a query sync object which is not in local subscribe map @@ -711,7 +711,7 @@ HWTEST_F(DistributedDBSingleVerP2PSubscribeSyncTest, subscribeManager006, TestSi * @tc.require: AR000FN6G9 * @tc.author: zhuwentao */ -HWTEST_F(DistributedDBSingleVerP2PSubscribeSyncTest, subscribeSync001, TestSize.Level1) +HWTEST_F(DistributedDBSingleVerP2PSubscribeSyncTest, SubscribeSync001, TestSize.Level1) { /** * @tc.steps: step1. InitSchemaDb @@ -776,7 +776,7 @@ HWTEST_F(DistributedDBSingleVerP2PSubscribeSyncTest, subscribeSync001, TestSize. * @tc.require: AR000FN6G9 * @tc.author: zhuwentao */ -HWTEST_F(DistributedDBSingleVerP2PSubscribeSyncTest, subscribeSync002, TestSize.Level1) +HWTEST_F(DistributedDBSingleVerP2PSubscribeSyncTest, SubscribeSync002, TestSize.Level1) { /** * @tc.steps: step1. InitSchemaDb @@ -820,7 +820,7 @@ HWTEST_F(DistributedDBSingleVerP2PSubscribeSyncTest, subscribeSync002, TestSize. * @tc.require: AR000GOHO7 * @tc.author: lidongwei */ -HWTEST_F(DistributedDBSingleVerP2PSubscribeSyncTest, subscribeSync003, TestSize.Level1) +HWTEST_F(DistributedDBSingleVerP2PSubscribeSyncTest, SubscribeSync003, TestSize.Level1) { /** * @tc.steps: step1. InitSchemaDb @@ -829,6 +829,7 @@ HWTEST_F(DistributedDBSingleVerP2PSubscribeSyncTest, subscribeSync003, TestSize. InitSubSchemaDb(); std::vector devices; devices.push_back(g_deviceB->GetDeviceId()); + g_deviceB->Online(); /** * @tc.steps: step2. deviceB subscribe inkeys(k2k4) query to deviceA @@ -1165,4 +1166,50 @@ HWTEST_F(DistributedDBSingleVerP2PSubscribeSyncTest, SubscribeSync012, TestSize. EXPECT_EQ(g_deviceB->GetData(key, item), E_OK); EXPECT_EQ(g_deviceC->GetData(key, item), -E_NOT_FOUND); } +} + +/** + * @tc.name: SubscribeSync014 + * @tc.desc: test device subscribe with put a lot of times + * @tc.type: FUNC + * @tc.require: AR000GOHO7 + * @tc.author: zhangqiquan + */ +HWTEST_F(DistributedDBSingleVerP2PSubscribeSyncTest, SubscribeSync014, TestSize.Level3) +{ + /** + * @tc.steps: step1. InitSchemaDb + */ + LOGI("============step 1============"); + InitSubSchemaDb(); + std::vector devices; + devices.push_back(g_deviceB->GetDeviceId()); + /** + * @tc.steps: step2. deviceB unsubscribe inkeys(k1, key6) and prefix key "k" query to deviceA + */ + LOGI("============step 2============"); + Key key6 { 'k', '6' }; + Query query = Query::Select(); + g_deviceB->Online(); + g_deviceB->Subscribe(QuerySyncObject(query), true, 1); + /** + * @tc.steps: step3. deviceA put a lot of time + * @tc.expected: step3 put performance was not effected by subscribe + */ + LOGI("============step 4============"); + std::vector dataKeys; + const uint64_t PUT_LIMIT_30S = 30 * 1000000; // 30s = 30 * 1000000us + LOGD("BEGIN PUT"); + for (uint8_t i = 0u; i < 10u; ++i) { // loop 10 times + Key key = { i }; + dataKeys.push_back(key); + uint64_t curTime = 0; + uint64_t lastTime = 0; + EXPECT_EQ(OS::GetCurrentSysTimeInMicrosecond(curTime), E_OK); + lastTime = curTime; + EXPECT_EQ(g_schemaKvDelegatePtr->Put(key, Value(SCHEMA_VALUE1.begin(), SCHEMA_VALUE1.end())), OK); + EXPECT_EQ(OS::GetCurrentSysTimeInMicrosecond(curTime), E_OK); + EXPECT_LE(curTime - lastTime, PUT_LIMIT_30S); + } + LOGD("END PUT"); } \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/mock_remote_executor.h b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/mock_remote_executor.h index bfab8c9d..d8c230bd 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/mock_remote_executor.h +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/mock_remote_executor.h @@ -25,9 +25,9 @@ public: MOCK_METHOD1(IsPacketValid, bool(uint32_t)); - void CallResponseFailed(int errCode, uint32_t sessionId, uint32_t sequenceId, const std::string &device) + int CallResponseFailed(int errCode, uint32_t sessionId, uint32_t sequenceId, const std::string &device) { - RemoteExecutor::ResponseFailed(errCode, sessionId, sequenceId, device); + return RemoteExecutor::ResponseFailed(errCode, sessionId, sequenceId, device); } }; } // namespace DistributedDB diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/mock_sync_task_context.h b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/mock_sync_task_context.h index 39dbab05..9cb58cc8 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/mock_sync_task_context.h +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/mock_sync_task_context.h @@ -92,6 +92,11 @@ public: } return SingleVerKvSyncTaskContext::GetDeviceId(); } + + void SetSyncOperation(SyncOperation *operation) + { + syncOperation_ = operation; + } private: std::function forkGetDeviceIdFunc_; }; diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_communicator_aggregator.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_communicator_aggregator.cpp index d3836d1a..31c89841 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_communicator_aggregator.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_communicator_aggregator.cpp @@ -313,4 +313,14 @@ void VirtualCommunicatorAggregator::DelayTimeHandle(uint32_t messageId, const st skipTimes_--; } } + +std::set VirtualCommunicatorAggregator::GetOnlineDevices() +{ + std::lock_guard lock(communicatorsLock_); + std::set onlineDevices; + for (const auto &item: communicators_) { + onlineDevices.insert(item.first); + } + return onlineDevices; +} } // namespace DistributedDB diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_communicator_aggregator.h b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_communicator_aggregator.h index 1c97716c..1f77ed02 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_communicator_aggregator.h +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_communicator_aggregator.h @@ -81,6 +81,8 @@ public: std::set &delayDevices); void ResetSendDelayInfo(); + std::set GetOnlineDevices(); + ~VirtualCommunicatorAggregator() {}; VirtualCommunicatorAggregator() {}; diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_single_ver_sync_db_Interface.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_single_ver_sync_db_Interface.cpp index 778b08f9..9ef22110 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_single_ver_sync_db_Interface.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_single_ver_sync_db_Interface.cpp @@ -138,6 +138,11 @@ int VirtualSingleVerSyncDBInterface::GetSyncDataNext(std::vector &data void VirtualSingleVerSyncDBInterface::ReleaseContinueToken(ContinueToken& continueStmtToken) const { + VirtualContinueToken *token = static_cast(continueStmtToken); + if (token != nullptr) { + delete token; + continueStmtToken = nullptr; + } return; } @@ -553,12 +558,12 @@ bool VirtualSingleVerSyncDBInterface::GetDataInner(Timestamp begin, Timestamp en { bool isFinished = true; for (const auto &data : dbData_) { - if (dataItems.size() >= dataSizeInfo.packetSize) { - LOGD("virtual device dataItem size reach to packetSize=%u", dataSizeInfo.packetSize); - isFinished = false; - break; - } if (data.isLocal) { + if (dataItems.size() >= dataSizeInfo.packetSize) { + LOGD("virtual device dataItem size reach to packetSize=%u", dataSizeInfo.packetSize); + isFinished = false; + break; + } if (data.writeTimestamp >= begin && data.writeTimestamp < end) { dataItems.push_back(data); currentWaterMark = data.writeTimestamp; diff --git a/kv_store/interfaces/innerkits/distributeddata/BUILD.gn b/kv_store/interfaces/innerkits/distributeddata/BUILD.gn index cfc75bdb..b78a26d2 100644 --- a/kv_store/interfaces/innerkits/distributeddata/BUILD.gn +++ b/kv_store/interfaces/innerkits/distributeddata/BUILD.gn @@ -47,7 +47,6 @@ config("distributeddatafwk_public_config") { include_dirs = [ "include", "../../../frameworks/innerkitsimpl/distributeddatafwk/include", - "//commonlibrary/c_utils/base/include", ] } @@ -99,7 +98,7 @@ external_deps_config = [ "hitrace_native:libhitracechain", "hiviewdfx_hilog_native:libhilog", "huks:libhukssdk", - "ipc:ipc_core", + "ipc:ipc_single", "samgr:samgr_proxy", ] diff --git a/kv_store/interfaces/innerkits/distributeddata/include/blob.h b/kv_store/interfaces/innerkits/distributeddata/include/blob.h index 88d4fff6..b7a59494 100644 --- a/kv_store/interfaces/innerkits/distributeddata/include/blob.h +++ b/kv_store/interfaces/innerkits/distributeddata/include/blob.h @@ -25,26 +25,44 @@ namespace DistributedKv { class Blob { public: + /** + * @brief Constructor. + */ API_EXPORT Blob(); + /** + * @brief Destructor. + */ API_EXPORT ~Blob() = default; /** * @brief Copy constructor for Blob. */ API_EXPORT Blob(const Blob &blob); + + /** + * @brief Operator =. + */ API_EXPORT Blob &operator=(const Blob &blob); /** * @brief Move constructor for Blob. */ API_EXPORT Blob(Blob &&blob); + + /** + * @brief Operator =. + */ API_EXPORT Blob &operator=(Blob &&blob); /** * @brief Construct a Blob use std::string. */ API_EXPORT Blob(const std::string &str); + + /** + * @brief Operator =. + */ API_EXPORT Blob &operator=(const std::string &str); /** @@ -56,6 +74,10 @@ public: * @brief Construct a Blob use char pointer. */ API_EXPORT Blob(const char *str); + + /** + * @brief Operator =. + */ API_EXPORT Blob &operator=(const char *str); /** @@ -73,8 +95,14 @@ public: */ API_EXPORT const std::vector &Data() const; + /** + * @brief Return std::vector &. + */ API_EXPORT operator const std::vector &() const; + /** + * @brief Return std::vector &&. + */ API_EXPORT operator std::vector &&() noexcept; /** @@ -102,6 +130,9 @@ public: */ API_EXPORT uint8_t operator[](size_t n) const; + /** + * @brief Operator ==. + */ API_EXPORT bool operator==(const Blob &) const; /** diff --git a/kv_store/interfaces/innerkits/distributeddata/include/change_notification.h b/kv_store/interfaces/innerkits/distributeddata/include/change_notification.h index d4cc84a9..c6bc3df1 100644 --- a/kv_store/interfaces/innerkits/distributeddata/include/change_notification.h +++ b/kv_store/interfaces/innerkits/distributeddata/include/change_notification.h @@ -34,6 +34,9 @@ public: API_EXPORT ChangeNotification(std::vector &&insertEntries, std::vector &&updateEntries, std::vector &&deleteEntries, const std::string &deviceId, bool isClear); + /** + * @brief Destructor. + */ API_EXPORT ~ChangeNotification(); /** diff --git a/kv_store/interfaces/innerkits/distributeddata/include/data_query.h b/kv_store/interfaces/innerkits/distributeddata/include/data_query.h index dc70626e..5daafcc9 100644 --- a/kv_store/interfaces/innerkits/distributeddata/include/data_query.h +++ b/kv_store/interfaces/innerkits/distributeddata/include/data_query.h @@ -28,8 +28,14 @@ namespace OHOS { namespace DistributedKv { class API_EXPORT DataQuery { public: + /** + * @brief Constructor. + */ DataQuery(); + /** + * @brief Destructor. + */ ~DataQuery() = default; /** diff --git a/kv_store/interfaces/innerkits/distributeddata/include/distributed_kv_data_manager.h b/kv_store/interfaces/innerkits/distributeddata/include/distributed_kv_data_manager.h index 016a079a..d87a7a2d 100644 --- a/kv_store/interfaces/innerkits/distributeddata/include/distributed_kv_data_manager.h +++ b/kv_store/interfaces/innerkits/distributeddata/include/distributed_kv_data_manager.h @@ -27,8 +27,14 @@ namespace OHOS { namespace DistributedKv { class API_EXPORT DistributedKvDataManager final { public: + /** + * @brief Constructor. + */ API_EXPORT DistributedKvDataManager(); + /** + * @brief Destructor. + */ API_EXPORT ~DistributedKvDataManager(); /** diff --git a/kv_store/interfaces/innerkits/distributeddata/include/kvstore.h b/kv_store/interfaces/innerkits/distributeddata/include/kvstore.h index 42046194..0e2e41b5 100644 --- a/kv_store/interfaces/innerkits/distributeddata/include/kvstore.h +++ b/kv_store/interfaces/innerkits/distributeddata/include/kvstore.h @@ -24,12 +24,24 @@ namespace OHOS { namespace DistributedKv { class API_EXPORT KvStore { public: + /** + * @brief Constructor. + */ API_EXPORT KvStore() = default; - // forbidden copy constructor. + /** + * @brief Forbidden copy constructor. + */ KvStore(const KvStore &) = delete; + + /** + * @brief Forbidden copy constructor. + */ KvStore &operator=(const KvStore &) = delete; + /** + * @brief Destructor. + */ API_EXPORT virtual ~KvStore() {} /** diff --git a/kv_store/interfaces/innerkits/distributeddata/include/kvstore_observer.h b/kv_store/interfaces/innerkits/distributeddata/include/kvstore_observer.h index 5cec165c..f50754d7 100644 --- a/kv_store/interfaces/innerkits/distributeddata/include/kvstore_observer.h +++ b/kv_store/interfaces/innerkits/distributeddata/include/kvstore_observer.h @@ -24,8 +24,14 @@ namespace DistributedKv { // client implement this class to watch kvstore change. class API_EXPORT KvStoreObserver { public: + /** + * @brief Constructor. + */ API_EXPORT KvStoreObserver() = default; + /** + * @brief Destructor. + */ API_EXPORT virtual ~KvStoreObserver() {} /** diff --git a/kv_store/interfaces/innerkits/distributeddata/include/kvstore_result_set.h b/kv_store/interfaces/innerkits/distributeddata/include/kvstore_result_set.h index 8965c7e5..42723c94 100644 --- a/kv_store/interfaces/innerkits/distributeddata/include/kvstore_result_set.h +++ b/kv_store/interfaces/innerkits/distributeddata/include/kvstore_result_set.h @@ -24,6 +24,10 @@ class KvStoreResultSet { public: inline static constexpr int INVALID_COUNT = -ALREADY_CLOSED; inline static constexpr int INVALID_POSITION = -ALREADY_CLOSED; + + /** + * @brief Destructor. + */ API_EXPORT virtual ~KvStoreResultSet() {} /** diff --git a/kv_store/interfaces/innerkits/distributeddata/include/kvstore_sync_callback.h b/kv_store/interfaces/innerkits/distributeddata/include/kvstore_sync_callback.h index 5820482a..3558026e 100644 --- a/kv_store/interfaces/innerkits/distributeddata/include/kvstore_sync_callback.h +++ b/kv_store/interfaces/innerkits/distributeddata/include/kvstore_sync_callback.h @@ -24,8 +24,14 @@ namespace DistributedKv { // client implement this class to watch kvstore change. class KvStoreSyncCallback { public: + /** + * @brief Constructor. + */ API_EXPORT KvStoreSyncCallback() = default; + /** + * @brief Destructor. + */ API_EXPORT virtual ~KvStoreSyncCallback() {} /** diff --git a/kv_store/interfaces/innerkits/distributeddata/include/single_kvstore.h b/kv_store/interfaces/innerkits/distributeddata/include/single_kvstore.h index 3dfa8c00..41d2e317 100644 --- a/kv_store/interfaces/innerkits/distributeddata/include/single_kvstore.h +++ b/kv_store/interfaces/innerkits/distributeddata/include/single_kvstore.h @@ -30,8 +30,14 @@ namespace DistributedKv { // This class provides put, delete, search, sync and subscribe functions of a key-value store. class API_EXPORT SingleKvStore : public virtual KvStore { public: + /** + * @brief Constructor. + */ API_EXPORT SingleKvStore() = default; + /** + * @brief Destructor. + */ API_EXPORT virtual ~SingleKvStore() {} /** diff --git a/kv_store/interfaces/innerkits/distributeddata/include/types.h b/kv_store/interfaces/innerkits/distributeddata/include/types.h index 467ca2ac..345515a9 100644 --- a/kv_store/interfaces/innerkits/distributeddata/include/types.h +++ b/kv_store/interfaces/innerkits/distributeddata/include/types.h @@ -66,6 +66,9 @@ struct API_EXPORT AppId { return appId; } + /** + * @brief Check appId. + */ inline bool IsValid() const { if (appId.empty() || appId.size() > MAX_APP_ID_LEN) { @@ -111,11 +114,17 @@ struct API_EXPORT StoreId { return storeId; } + /** + * @brief Operator <. + */ bool operator<(const StoreId &id) const noexcept { return this->storeId < id.storeId; } + /** + * @brief Check storeId. + */ inline bool IsValid() const { if (storeId.empty() || storeId.size() > MAX_STORE_ID_LEN) { @@ -398,25 +407,6 @@ struct Options { return kvStoreType == KvStoreType::DEVICE_COLLABORATION || kvStoreType == KvStoreType::SINGLE_VERSION; } }; - -template -std::vector TransferTypeToByteArray(const T &t) -{ - return std::vector(reinterpret_cast(const_cast(&t)), - reinterpret_cast(const_cast(&t)) + sizeof(T)); -} - -template -T TransferByteArrayToType(const std::vector &blob) -{ - // replace assert to HILOG_FATAL when HILOG_FATAL is ok. - if (blob.size() != sizeof(T) || blob.size() == 0) { - constexpr int tSize = sizeof(T); - uint8_t tContent[tSize] = { 0 }; - return *reinterpret_cast(tContent); - } - return *reinterpret_cast(const_cast(&blob[0])); -} } // namespace DistributedKv } // namespace OHOS #endif // DISTRIBUTED_KVSTORE_TYPES_H diff --git a/kv_store/interfaces/jskits/distributeddata/BUILD.gn b/kv_store/interfaces/jskits/distributeddata/BUILD.gn index b250c263..f6bef6be 100644 --- a/kv_store/interfaces/jskits/distributeddata/BUILD.gn +++ b/kv_store/interfaces/jskits/distributeddata/BUILD.gn @@ -73,6 +73,7 @@ ohos_shared_library("distributeddata") { "ability_runtime:abilitykit_native", "ability_runtime:napi_base_context", "c_utils:utils", + "common_event_service:cesfwk_innerkits", "hiviewdfx_hilog_native:libhilog", "ipc:ipc_single", "kv_store:distributeddata_inner", diff --git a/kv_store/interfaces/jskits/distributedkvstore/BUILD.gn b/kv_store/interfaces/jskits/distributedkvstore/BUILD.gn index c61d8ebd..2755f5f3 100644 --- a/kv_store/interfaces/jskits/distributedkvstore/BUILD.gn +++ b/kv_store/interfaces/jskits/distributedkvstore/BUILD.gn @@ -73,6 +73,7 @@ ohos_shared_library("distributedkvstore") { "ability_runtime:abilitykit_native", "ability_runtime:napi_base_context", "c_utils:utils", + "common_event_service:cesfwk_innerkits", "hiviewdfx_hilog_native:libhilog", "ipc:ipc_single", "kv_store:distributeddata_inner", diff --git a/kv_store/kvstoremock/distributeddb/BUILD.gn b/kv_store/kvstoremock/distributeddb/BUILD.gn index 51140db0..a35db118 100644 --- a/kv_store/kvstoremock/distributeddb/BUILD.gn +++ b/kv_store/kvstoremock/distributeddb/BUILD.gn @@ -79,6 +79,7 @@ config("distrdb_config") { defines += [ "EVLOOP_TIMER_ONLY", "USING_PRINTF_LOGGER", + "OPENSSL_SUPPRESS_DEPRECATED", ] if (use_platform_win) { defines += [ "OS_TYPE_WINDOWS" ] diff --git a/kv_store/test/fuzztest/typesutil_fuzzer/BUILD.gn b/kv_store/test/fuzztest/typesutil_fuzzer/BUILD.gn index 7298912c..77818a65 100644 --- a/kv_store/test/fuzztest/typesutil_fuzzer/BUILD.gn +++ b/kv_store/test/fuzztest/typesutil_fuzzer/BUILD.gn @@ -49,7 +49,7 @@ ohos_fuzztest("TypesUtilFuzzTest") { external_deps = [ "c_utils:utils", "hiviewdfx_hilog_native:libhilog", - "ipc:ipc_core", + "ipc:ipc_single", "kv_store:distributeddata_inner", ] } diff --git a/kv_store/test/unittest/distributeddata/SingleKvStoreDataCallbackJsTest.js b/kv_store/test/unittest/distributeddata/SingleKvStoreDataCallbackJsTest.js index a1cded91..ed175f0c 100644 --- a/kv_store/test/unittest/distributeddata/SingleKvStoreDataCallbackJsTest.js +++ b/kv_store/test/unittest/distributeddata/SingleKvStoreDataCallbackJsTest.js @@ -1951,27 +1951,6 @@ describe('singleKvStoreCallbackTest', function () { } }) - /** - * @tc.name SingleKvStoreGetSecurityLevelCallbackTest001 - * @tc.desc Test Js Api SingleKvStore.GetSecurityLevel() testcase 001 - * @tc.type: FUNC - * @tc.require: issueNumber - */ - // it('SingleKvStoreGetSecurityLevelCallbackTest001', 0, async function (done) { - // console.info('SingleKvStoreGetSecurityLevelCallbackTest001'); - // try { - // await kvStore.getSecurityLevel(function (err,data) { - // console.info('SingleKvStoreGetSecurityLevelCallbackTest001 getSecurityLevel success'); - // expect(data == factory.SecurityLevel.S2).assertTrue(); - // done(); - // }); - // }catch(e) { - // console.error('SingleKvStoreGetSecurityLevelCallbackTest001 e ' + `, error code is ${e.code}, message is ${e.message}`); - // expect(null).assertFail(); - // done(); - // } - // }) - /** * @tc.name SingleKvStoreGetSecurityLevelCallbackTest002 * @tc.desc Test Js Api SingleKvStore.GetSecurityLevel() testcase 002 diff --git a/kv_store/test/unittest/distributeddata/SingleKvStoreDataPromiseJsTest.js b/kv_store/test/unittest/distributeddata/SingleKvStoreDataPromiseJsTest.js index ed96a3ba..a064c1b1 100644 --- a/kv_store/test/unittest/distributeddata/SingleKvStoreDataPromiseJsTest.js +++ b/kv_store/test/unittest/distributeddata/SingleKvStoreDataPromiseJsTest.js @@ -2146,29 +2146,6 @@ describe('singleKvStorePromiseTest', function () { done(); }) - /** - * @tc.name SingleKvStoreGetSecurityLevelPromiseTest001 - * @tc.desc Test Js Api SingleKvStoreGetSecurityLevel testcase 001 - * @tc.type: FUNC - * @tc.require: issueNumber - */ - // it('SingleKvStoreGetSecurityLevelPromiseTest001', 0, async function (done) { - // console.info('SingleKvStoreGetSecurityLevelPromiseTest001'); - // try { - // await kvStore.getSecurityLevel().then((data) => { - // console.info('SingleKvStoreGetSecurityLevelPromiseTest001 getSecurityLevel success'); - // expect(data == factory.SecurityLevel.S2).assertTrue(); - // }).catch((err) => { - // console.error('SingleKvStoreGetSecurityLevelPromiseTest001 getSecurityLevel fail ' + `, error code is ${err.code}, message is ${err.message}`); - // expect(null).assertFail(); - // }); - // }catch(e) { - // console.error('SingleKvStoreGetSecurityLevelPromiseTest001 e ' + `, error code is ${e.code}, message is ${e.message}`); - // expect(null).assertFail(); - // } - // done(); - // }) - /** * @tc.name SingleKvStoreGetSecurityLevelPromiseTest002 * @tc.desc Test Js Api SingleKvStoreGetSecurityLevel testcase 002 diff --git a/mock/innerkits/ability_runtime/runtime/include/js_runtime.h b/mock/innerkits/ability_runtime/runtime/include/js_runtime.h index 00686247..a31a23cb 100644 --- a/mock/innerkits/ability_runtime/runtime/include/js_runtime.h +++ b/mock/innerkits/ability_runtime/runtime/include/js_runtime.h @@ -52,6 +52,8 @@ public: std::unique_ptr LoadModule( const std::string& moduleName, const std::string& modulePath, bool esmodule = false); + std::unique_ptr LoadModule(const std::string &moduleName, const std::string &modulePath, + bool hapPath, bool esmodule = false); std::unique_ptr LoadSystemModule( const std::string& moduleName, NativeValue* const* argv = nullptr, size_t argc = 0); void PostTask(const std::function& task, const std::string& name, int64_t delayTime); diff --git a/datamgr_service/services/distributeddataservice/framework/store/general_watcher.cpp b/mock/innerkits/appexecfwk_base/include/bundle_common_event.h similarity index 39% rename from datamgr_service/services/distributeddataservice/framework/store/general_watcher.cpp rename to mock/innerkits/appexecfwk_base/include/bundle_common_event.h index 336d4ce8..ec4d5cb6 100644 --- a/datamgr_service/services/distributeddataservice/framework/store/general_watcher.cpp +++ b/mock/innerkits/appexecfwk_base/include/bundle_common_event.h @@ -13,4 +13,24 @@ * limitations under the License. */ -#include "store/general_watcher.h" +#ifndef FOUNDATION_BUNDLEMANAGER_BUNDLE_FRAMEWORK_INNERKITS_APPEXECFWK_BASE_INCLUDE_BUNDLE_COMMON_EVENT_H +#define FOUNDATION_BUNDLEMANAGER_BUNDLE_FRAMEWORK_INNERKITS_APPEXECFWK_BASE_INCLUDE_BUNDLE_COMMON_EVENT_H + +#include + +namespace OHOS { +namespace AppExecFwk { +const std::string COMMON_EVENT_SANDBOX_PACKAGE_ADDED = "usual.event.SANDBOX_PACKAGE_ADDED"; + +const std::string COMMON_EVENT_SANDBOX_PACKAGE_REMOVED = "usual.event.SANDBOX_PACKAGE_REMOVED"; + +const std::string COMMON_EVENT_BUNDLE_SCAN_FINISHED = "usual.event.BUNDLE_SCAN_FINISHED"; + +const std::string OVERLAY_ADD_ACTION = "usual.event.OVERLAY_PACKAGE_ADDED"; + +const std::string OVERLAY_CHANGED_ACTION = "usual.event.OVERLAY_PACKAGE_CHANGED"; + +const std::string OVERLAY_STATE_CHANGED = "usual.event.OVERLAY_STATE_CHANGED"; +} // AppExecFwk +} // OHOS +#endif // FOUNDATION_BUNDLEMANAGER_BUNDLE_FRAMEWORK_INNERKITS_APPEXECFWK_BASE_INCLUDE_BUNDLE_COMMON_EVENT_H \ No newline at end of file diff --git a/mock/innerkits/device_manager/devicemanagersdk/include/device_manager.h b/mock/innerkits/device_manager/devicemanagersdk/include/device_manager.h index 6128e720..ffccadc0 100644 --- a/mock/innerkits/device_manager/devicemanagersdk/include/device_manager.h +++ b/mock/innerkits/device_manager/devicemanagersdk/include/device_manager.h @@ -208,7 +208,10 @@ public: */ virtual int32_t NotifyEvent(const std::string &pkgName, const int32_t eventId, const std::string &event) = 0; - virtual int GetEncryptedUuidByNetworkId(const std::string &pkgName, const std::string &networkId, std::string &uuid) = 0; + virtual int GetEncryptedUuidByNetworkId(const std::string &pkgName, const std::string &networkId, + std::string &uuid) = 0; + virtual int GenerateEncryptedUuid(const std::string &pkgName, const std::string &uuid, const std::string &appId, + std::string &encryptedUuid) = 0; }; } // namespace DistributedHardware } // namespace OHOS diff --git a/mock/innerkits/device_manager/devicemanagersdk/include/device_manager_impl.h b/mock/innerkits/device_manager/devicemanagersdk/include/device_manager_impl.h index fa122c34..068ddf0b 100644 --- a/mock/innerkits/device_manager/devicemanagersdk/include/device_manager_impl.h +++ b/mock/innerkits/device_manager/devicemanagersdk/include/device_manager_impl.h @@ -205,6 +205,8 @@ public: int GetEncryptedUuidByNetworkId(const std::string &pkgName, const std::string &networkId, std::string &uuid) override; + int GenerateEncryptedUuid(const std::string &pkgName, const std::string &uuid, const std::string &appId, + std::string &encryptedUuid) override; private: DeviceManagerImpl() = default; diff --git a/mock/src/mock_device_manager.cpp b/mock/src/mock_device_manager.cpp index f0762595..7e153983 100644 --- a/mock/src/mock_device_manager.cpp +++ b/mock/src/mock_device_manager.cpp @@ -177,4 +177,11 @@ int32_t DeviceManagerImpl::NotifyEvent(const std::string &pkgName, const int32_t { return 0; } + +int DeviceManagerImpl::GenerateEncryptedUuid(const std::string &pkgName, const std::string &uuid, + const std::string &appId, std::string &encryptedUuid) +{ + encryptedUuid = uuid; + return 0; +} } \ No newline at end of file diff --git a/mock/src/mock_js_runtime.cpp b/mock/src/mock_js_runtime.cpp index d64fc248..7f44cec3 100644 --- a/mock/src/mock_js_runtime.cpp +++ b/mock/src/mock_js_runtime.cpp @@ -46,6 +46,11 @@ std::unique_ptr JsRuntime::LoadModule(const std::string &module { return std::unique_ptr(); } +std::unique_ptr JsRuntime::LoadModule(const std::string &moduleName, const std::string &modulePath, + bool hapPath, bool esmodule) +{ + return std::unique_ptr(); +} std::unique_ptr JsRuntime::LoadSystemModule(const std::string &moduleName, NativeValue *const *argv, size_t argc) { diff --git a/preferences/frameworks/js/napi/preferences/BUILD.gn b/preferences/frameworks/js/napi/preferences/BUILD.gn index c102cf43..f63e0978 100644 --- a/preferences/frameworks/js/napi/preferences/BUILD.gn +++ b/preferences/frameworks/js/napi/preferences/BUILD.gn @@ -46,6 +46,7 @@ if (!is_mingw && !is_mac) { external_deps = [ "ability_runtime:abilitykit_native", "ability_runtime:napi_base_context", + "common_event_service:cesfwk_innerkits", "hilog_native:libhilog", "napi:ace_napi", "preferences:native_preferences", diff --git a/preferences/frameworks/js/napi/preferences/src/napi_preferences.cpp b/preferences/frameworks/js/napi/preferences/src/napi_preferences.cpp index 5918a882..9da824be 100644 --- a/preferences/frameworks/js/napi/preferences/src/napi_preferences.cpp +++ b/preferences/frameworks/js/napi/preferences/src/napi_preferences.cpp @@ -115,7 +115,7 @@ napi_status PreferencesProxy::NewInstance( LOG_ERROR("PreferencesProxy::NewInstance unwarp native preferences is null"); return napi_generic_failure; } - proxy->value_ = std::move(value); + proxy->value_ = value; return napi_ok; } @@ -127,7 +127,11 @@ napi_value PreferencesProxy::New(napi_env env, napi_callback_info info) LOG_WARN("get this failed"); return nullptr; } - PreferencesProxy *obj = new PreferencesProxy(); + PreferencesProxy *obj = new (std::nothrow) PreferencesProxy(); + if (obj == nullptr) { + LOG_ERROR("PreferencesProxy::New new failed, obj is nullptr"); + return nullptr; + } obj->env_ = env; obj->uvQueue_ = std::make_shared(env); napi_status status = napi_wrap(env, thiz, obj, PreferencesProxy::Destructor, nullptr, nullptr); @@ -300,6 +304,9 @@ int ParseDefValue(const napi_env &env, const napi_value &jsVal, std::shared_ptr< } else if (valueType == napi_object) { if (ParseDefObject(env, jsVal, context) != E_OK) { LOG_ERROR("ParseDefValue::ParseDefObject failed"); + std::shared_ptr paramError = std::make_shared("value", "a ValueType."); + context->SetError(paramError); + return ERR; } } else { LOG_ERROR("ParseDefValue Wrong second parameter type"); diff --git a/preferences/frameworks/js/napi/storage/src/napi_storage.cpp b/preferences/frameworks/js/napi/storage/src/napi_storage.cpp index e0dffd71..b7f082b7 100644 --- a/preferences/frameworks/js/napi/storage/src/napi_storage.cpp +++ b/preferences/frameworks/js/napi/storage/src/napi_storage.cpp @@ -131,7 +131,11 @@ napi_value StorageProxy::New(napi_env env, napi_callback_info info) napi_valuetype valueType = napi_undefined; NAPI_CALL(env, napi_typeof(env, args[0], &valueType)); NAPI_ASSERT(env, valueType == napi_string, "input type not string"); - char *path = new char[PATH_MAX]; + char *path = new (std::nothrow) char[PATH_MAX]; + if (path == nullptr) { + LOG_ERROR("StorageProxy::New new failed, path is nullptr"); + return nullptr; + } size_t pathLen = 0; napi_status status = napi_get_value_string_utf8(env, args[0], path, PATH_MAX, &pathLen); if (status != napi_ok) { @@ -145,7 +149,11 @@ napi_value StorageProxy::New(napi_env env, napi_callback_info info) OHOS::NativePreferences::PreferencesHelper::GetPreferences(path, errCode); delete[] path; NAPI_ASSERT(env, preference != nullptr, "failed to call native"); - StorageProxy *obj = new StorageProxy(preference); + StorageProxy *obj = new (std::nothrow) StorageProxy(preference); + if (obj == nullptr) { + LOG_ERROR("StorageProxy::New new failed, obj is nullptr"); + return nullptr; + } obj->env_ = env; obj->value_ = std::move(preference); obj->uvQueue_ = std::make_shared(env); @@ -221,7 +229,11 @@ napi_value StorageProxy::GetValueSync(napi_env env, napi_callback_info info) double result = obj->value_->GetDouble(key, value); NAPI_CALL(env, napi_create_double(env, result, &output)); // double } else if (valueType == napi_string) { - char *value = new char[MAX_VALUE_LENGTH]; + char *value = new (std::nothrow) char[MAX_VALUE_LENGTH]; + if (value == nullptr) { + LOG_ERROR("StorageProxy::GetValueSync new failed, value is nullptr"); + return nullptr; + } size_t valueSize = 0; napi_get_value_string_utf8(env, args[1], value, MAX_VALUE_LENGTH, &valueSize); // get value diff --git a/preferences/frameworks/js/napi/storage/src/napi_storage_helper.cpp b/preferences/frameworks/js/napi/storage/src/napi_storage_helper.cpp index fbc613fe..d7b85f29 100644 --- a/preferences/frameworks/js/napi/storage/src/napi_storage_helper.cpp +++ b/preferences/frameworks/js/napi/storage/src/napi_storage_helper.cpp @@ -57,7 +57,11 @@ int ParseString(const napi_env &env, const napi_value &value, std::shared_ptrpath = path; @@ -108,7 +112,11 @@ napi_status GetInputPath(napi_env env, napi_callback_info info, std::string &pat return napi_invalid_arg; } - char *path = new char[PATH_MAX]; + char *path = new (std::nothrow) char[PATH_MAX]; + if (path == nullptr) { + LOG_ERROR("GetInputPath new failed, path is nullptr"); + return napi_arraybuffer_expected; + } size_t pathLen = 0; ret = napi_get_value_string_utf8(env, args[0], path, PATH_MAX, &pathLen); pathString = path; diff --git a/preferences/frameworks/js/napi/system_storage/BUILD.gn b/preferences/frameworks/js/napi/system_storage/BUILD.gn index 0be50f75..f284a443 100644 --- a/preferences/frameworks/js/napi/system_storage/BUILD.gn +++ b/preferences/frameworks/js/napi/system_storage/BUILD.gn @@ -43,6 +43,7 @@ if (!is_mingw && !is_mac) { external_deps = [ "ability_runtime:abilitykit_native", "ability_runtime:napi_base_context", + "common_event_service:cesfwk_innerkits", "hilog_native:libhilog", "napi:ace_napi", "preferences:native_preferences", diff --git a/preferences/frameworks/js/napi/system_storage/src/napi_system_storage.cpp b/preferences/frameworks/js/napi/system_storage/src/napi_system_storage.cpp index e1f0f06c..1c11411d 100644 --- a/preferences/frameworks/js/napi/system_storage/src/napi_system_storage.cpp +++ b/preferences/frameworks/js/napi/system_storage/src/napi_system_storage.cpp @@ -157,7 +157,11 @@ napi_value Operate(napi_env env, napi_callback_info info, const char *resource, NAPI_CALL(env, napi_typeof(env, argv[0], &valueType)); NAPI_ASSERT(env, valueType == napi_object, "Wrong argument type, object expected."); - AsyncContext *context = new AsyncContext(); + AsyncContext *context = new (std::nothrow) AsyncContext(); + if (context == nullptr) { + LOG_ERROR("Operate new failed, context is nullptr"); + return nullptr; + } context->prefName = GetPrefName(env); ParseString(env, argv[0], "key", parseStrFlag, context->key); diff --git a/preferences/frameworks/native/include/preferences_impl.h b/preferences/frameworks/native/include/preferences_impl.h index ead876e6..c286308c 100644 --- a/preferences/frameworks/native/include/preferences_impl.h +++ b/preferences/frameworks/native/include/preferences_impl.h @@ -29,7 +29,6 @@ #include "preferences.h" #include "preferences_observer.h" #include "preferences_value.h" -#include "task_pool.h" namespace OHOS { namespace NativePreferences { @@ -168,12 +167,11 @@ private: int writeToDiskResult_; bool wasWritten_; - bool handled_; }; std::shared_ptr commitToMemory(); void notifyPreferencesObserver(const MemoryToDiskRequest &request); - void StartLoadFromDisk(); + bool StartLoadFromDisk(); int CheckKey(const std::string &key); int CheckStringValue(const std::string &value); @@ -203,12 +201,6 @@ private: const std::string filePath_; const std::string backupPath_; const std::string brokenPath_; - // Task pool - /* max threads of the task pool. */ - static constexpr int MAX_TP_THREADS = 10; - /* min threads of the task pool. */ - static constexpr int MIN_TP_THREADS = 1; - TaskPool taskPool_; }; } // End of namespace NativePreferences } // End of namespace OHOS diff --git a/preferences/frameworks/native/include/task_executor.h b/preferences/frameworks/native/include/task_executor.h new file mode 100644 index 00000000..38b44a65 --- /dev/null +++ b/preferences/frameworks/native/include/task_executor.h @@ -0,0 +1,35 @@ +/* +* Copyright (c) 2023 Huawei Device Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +#ifndef PREFERENCES_TASK_EXECUTOR_H +#define PREFERENCES_TASK_EXECUTOR_H +#include + +#include "task_scheduler.h" +namespace OHOS { +namespace NativePreferences { +class TaskExecutor { +public: + API_LOCAL static TaskExecutor &GetInstance(); + API_LOCAL bool Execute(TaskScheduler::Task &&task); + +private: + TaskExecutor(); + ~TaskExecutor(); + + std::shared_ptr pool_; +}; +} // namespace NativePreferences +} // namespace OHOS +#endif // PREFERENCES_TASK_EXECUTOR_H diff --git a/preferences/frameworks/native/include/task_scheduler.h b/preferences/frameworks/native/include/task_scheduler.h new file mode 100644 index 00000000..33eb71f3 --- /dev/null +++ b/preferences/frameworks/native/include/task_scheduler.h @@ -0,0 +1,127 @@ +/* + * 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_PREFERENCES_FRAMEWORKS_COMMON_TASK_SCHEDULER_H +#define OHOS_PREFERENCES_FRAMEWORKS_COMMON_TASK_SCHEDULER_H +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "visibility.h" +namespace OHOS { +class API_LOCAL TaskScheduler { +public: + using TaskId = uint64_t; + using Time = std::chrono::steady_clock::time_point; + using Task = std::function; + inline static constexpr TaskId INVALID_TASK_ID = static_cast(0ULL); + TaskScheduler(const std::string &name) + { + capacity_ = std::numeric_limits::max(); + isRunning_ = true; + taskId_ = INVALID_TASK_ID; + thread_ = std::make_unique([this, name]() { + auto realName = std::string("task_queue_") + name; +#if defined(MAC_PLATFORM) + pthread_setname_np(realName.c_str()); +#else + pthread_setname_np(pthread_self(), realName.c_str()); +#endif + Loop(); + }); + } + + ~TaskScheduler() + { + isRunning_ = false; + { + std::unique_lock lock(mutex_); + indexes_.clear(); + tasks_.clear(); + } + At(std::chrono::steady_clock::now(), []() {}); + thread_->join(); + } + + // execute task at specific time + TaskId At(const Time &time, Task task) + { + std::unique_lock lock(mutex_); + if (tasks_.size() >= capacity_) { + return INVALID_TASK_ID; + } + auto taskId = GenTaskId(); + auto it = tasks_.insert({ time, std::pair{ task, taskId } }); + if (it == tasks_.begin()) { + condition_.notify_one(); + } + indexes_[taskId] = it; + return taskId; + } + + TaskId Execute(Task task) + { + return At(std::chrono::steady_clock::now(), std::move(task)); + } + +private: + using InnerTask = std::pair, uint64_t>; + void Loop() + { + while (isRunning_) { + std::function exec; + { + std::unique_lock lock(mutex_); + condition_.wait(lock, [this] { return !tasks_.empty(); }); + auto it = tasks_.begin(); + exec = it->second.first; + indexes_.erase(it->second.second); + tasks_.erase(it); + } + + if (exec) { + exec(); + } + } + } + + TaskId GenTaskId() + { + auto taskId = ++taskId_; + if (taskId == INVALID_TASK_ID) { + return ++taskId_; + } + return taskId; + } + + volatile bool isRunning_; + size_t capacity_; + std::multimap tasks_; + std::map indexes_; + std::mutex mutex_; + std::unique_ptr thread_; + std::condition_variable condition_; + std::atomic taskId_; +}; +} // namespace OHOS +#endif // OHOS_PREFERENCES_FRAMEWORKS_COMMON_TASK_SCHEDULER_H diff --git a/datamgr_service/services/distributeddataservice/framework/store/asset.cpp b/preferences/frameworks/native/include/visibility.h similarity index 64% rename from datamgr_service/services/distributeddataservice/framework/store/asset.cpp rename to preferences/frameworks/native/include/visibility.h index 4fc843b6..7c7726f4 100644 --- a/datamgr_service/services/distributeddataservice/framework/store/asset.cpp +++ b/preferences/frameworks/native/include/visibility.h @@ -13,4 +13,14 @@ * limitations under the License. */ -#include "store/asset.h" +#ifndef OHOS_PREFERENCES_FRAMEWORKS_COMMON_VISIBILITY_H +#define OHOS_PREFERENCES_FRAMEWORKS_COMMON_VISIBILITY_H + +#ifndef API_EXPORT +#define API_EXPORT __attribute__((visibility("default"))) +#endif +#ifndef API_LOCAL +#define API_LOCAL __attribute__((visibility("hidden"))) +#endif + +#endif // OHOS_PREFERENCES_FRAMEWORKS_COMMON_VISIBILITY_H diff --git a/preferences/frameworks/native/src/preferences_helper.cpp b/preferences/frameworks/native/src/preferences_helper.cpp index 3c8e0992..a6624c5e 100644 --- a/preferences/frameworks/native/src/preferences_helper.cpp +++ b/preferences/frameworks/native/src/preferences_helper.cpp @@ -108,6 +108,7 @@ std::shared_ptr PreferencesHelper::GetPreferences(const std::string std::shared_ptr pref = std::make_shared(filePath); errCode = pref->Init(); if (errCode != E_OK) { + LOG_ERROR("Preferences Init failed."); return nullptr; } prefsCache_.insert(make_pair(realPath, pref)); diff --git a/preferences/frameworks/native/src/preferences_impl.cpp b/preferences/frameworks/native/src/preferences_impl.cpp index 03166967..70db5c79 100644 --- a/preferences/frameworks/native/src/preferences_impl.cpp +++ b/preferences/frameworks/native/src/preferences_impl.cpp @@ -20,13 +20,15 @@ #include #include #include +#include +#include "adaptor.h" #include "logger.h" #include "preferences_errno.h" #include "preferences_xml_utils.h" #include "securec.h" - -#include "adaptor.h" +#include "task_executor.h" +#include "task_scheduler.h" namespace OHOS { namespace NativePreferences { @@ -48,7 +50,7 @@ static bool IsFileExist(const std::string &inputPath) PreferencesImpl::PreferencesImpl(const std::string &filePath) : loaded_(false), filePath_(filePath), backupPath_(MakeBackupPath(filePath_)), - brokenPath_(MakeBrokenPath(filePath_)), taskPool_(TaskPool(MAX_TP_THREADS, MIN_TP_THREADS)) + brokenPath_(MakeBrokenPath(filePath_)) { currentMemoryStateGeneration_ = 0; diskStateGeneration_ = 0; @@ -70,26 +72,24 @@ std::string PreferencesImpl::MakeBrokenPath(const std::string &prefPath) PreferencesImpl::~PreferencesImpl() { - taskPool_.Stop(); } int PreferencesImpl::Init() { - int errCode = taskPool_.Start(); - if (errCode != E_OK) { - return errCode; + if (!StartLoadFromDisk()) { + return E_ERROR; } - StartLoadFromDisk(); return E_OK; } -void PreferencesImpl::StartLoadFromDisk() +bool PreferencesImpl::StartLoadFromDisk() { { std::lock_guard lock(mutex_); loaded_ = false; } - taskPool_.Schedule(std::string("PreferencesImpl"), std::bind(&PreferencesImpl::LoadFromDisk, std::ref(*this))); + TaskScheduler::Task task = std::bind(PreferencesImpl::LoadFromDisk, std::ref(*this)); + return TaskExecutor::GetInstance().Execute(std::move(task)); } int PreferencesImpl::CheckKey(const std::string &key) @@ -144,12 +144,7 @@ void PreferencesImpl::AwaitLoadFile() void PreferencesImpl::WriteToDiskFile(std::shared_ptr mcr) { - bool fileExists = false; if (IsFileExist(filePath_)) { - fileExists = true; - } - - if (fileExists) { bool needWrite = CheckRequestValidForStateGeneration(*mcr); if (!needWrite) { mcr->SetDiskWriteResult(false, E_OK); @@ -227,7 +222,7 @@ std::map PreferencesImpl::GetAll() return map_; } -void ReadXmlArrayElement(Element element, std::map &prefMap) +void ReadXmlArrayElement(const Element &element, std::map &prefMap) { if (element.tag_.compare("doubleArray") == 0) { std::vector values; @@ -259,7 +254,7 @@ void ReadXmlArrayElement(Element element, std::map &prefMap, const std::string &prefPath) + const Element &element, std::map &prefMap, const std::string &prefPath) { if (element.tag_.compare("int") == 0) { std::stringstream ss; @@ -306,15 +301,14 @@ bool PreferencesImpl::ReadSettingXml( LOG_ERROR("ReadSettingXml:%{private}s failed!", filePath_.c_str()); return false; } - - for (auto it = settings.begin(); it != settings.end(); it++) { - Element element = *it; + + for (const auto &element : settings) { ReadXmlElement(element, prefMap, prefPath); } return true; } -void WriteXmlElement(Element &elem, PreferencesValue value, const std::string filePath) +void WriteXmlElement(Element &elem, const PreferencesValue &value, const std::string &filePath) { if (value.IsDoubleArray()) { elem.tag_ = std::string("doubleArray"); @@ -492,9 +486,9 @@ void PreferencesImpl::Flush() DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__)); std::shared_ptr request = commitToMemory(); request->isSyncRequest_ = false; - - taskPool_.Schedule( - std::string("PreferencesImpl"), std::bind(&PreferencesImpl::WriteToDiskFile, std::ref(*this), request)); + TaskScheduler::Task task = std::bind(&PreferencesImpl::WriteToDiskFile, std::ref(*this), request); + TaskExecutor::GetInstance().Execute(std::move(task)); + notifyPreferencesObserver(*request); } @@ -502,15 +496,11 @@ int PreferencesImpl::FlushSync() { std::shared_ptr request = commitToMemory(); request->isSyncRequest_ = true; - - taskPool_.Schedule( - std::string("PreferencesImpl"), std::bind(&PreferencesImpl::WriteToDiskFile, std::ref(*this), request)); std::unique_lock lock(request->reqMutex_); - request->reqCond_.wait(lock, [request] { return request->handled_; }); + WriteToDiskFile(request); if (request->wasWritten_) { LOG_DEBUG("%{private}s:%{public}" PRId64 " written", filePath_.c_str(), request->memoryStateGeneration_); } - notifyPreferencesObserver(*request); return request->writeToDiskResult_; } @@ -559,7 +549,6 @@ PreferencesImpl::MemoryToDiskRequest::MemoryToDiskRequest( preferencesObservers_ = preferencesObservers; memoryStateGeneration_ = memStataGeneration; isSyncRequest_ = false; - handled_ = false; wasWritten_ = false; writeToDiskResult_ = E_ERROR; } @@ -568,7 +557,6 @@ void PreferencesImpl::MemoryToDiskRequest::SetDiskWriteResult(bool wasWritten, i { writeToDiskResult_ = result; wasWritten_ = wasWritten; - handled_ = true; reqCond_.notify_one(); } } // End of namespace NativePreferences diff --git a/preferences/frameworks/native/src/task_executor.cpp b/preferences/frameworks/native/src/task_executor.cpp new file mode 100644 index 00000000..2bfb6a07 --- /dev/null +++ b/preferences/frameworks/native/src/task_executor.cpp @@ -0,0 +1,43 @@ +/* +* 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. +*/ +#include "task_executor.h" + +namespace OHOS { +namespace NativePreferences { +TaskExecutor &TaskExecutor::GetInstance() +{ + static TaskExecutor instance; + return instance; +} + +bool TaskExecutor::Execute(TaskScheduler::Task &&task) +{ + if (pool_ == nullptr) { + return false; + } + pool_->Execute(std::move(task)); + return true; +} + +TaskExecutor::TaskExecutor() +{ + pool_ = std::make_shared("preferences"); +} + +TaskExecutor::~TaskExecutor() +{ +} +} // namespace NativePreferences +} // namespace OHOS diff --git a/preferences/interfaces/inner_api/BUILD.gn b/preferences/interfaces/inner_api/BUILD.gn index 7ee913a5..e0210d6b 100644 --- a/preferences/interfaces/inner_api/BUILD.gn +++ b/preferences/interfaces/inner_api/BUILD.gn @@ -35,8 +35,7 @@ base_sources = [ "${preferences_native_path}/src/preferences_observer.cpp", "${preferences_native_path}/src/preferences_value.cpp", "${preferences_native_path}/src/preferences_xml_utils.cpp", - "${preferences_native_path}/src/task_pool.cpp", - "${preferences_native_path}/src/task_queue.cpp", + "${preferences_native_path}/src/task_executor.cpp", ] ohos_shared_library("native_preferences") { diff --git a/preferences/test/native/unittest/preferences_test.cpp b/preferences/test/native/unittest/preferences_test.cpp index 3501bc33..83372c1d 100644 --- a/preferences/test/native/unittest/preferences_test.cpp +++ b/preferences/test/native/unittest/preferences_test.cpp @@ -84,7 +84,7 @@ void PreferencesTest::TearDown(void) /* clear all data after every case */ if (pref) { pref->Clear(); - pref->Flush(); + pref->FlushSync(); } } diff --git a/preferences/test/native/unittest/preferences_xml_utils_test.cpp b/preferences/test/native/unittest/preferences_xml_utils_test.cpp index 3ac9e141..d7295127 100644 --- a/preferences/test/native/unittest/preferences_xml_utils_test.cpp +++ b/preferences/test/native/unittest/preferences_xml_utils_test.cpp @@ -103,7 +103,7 @@ HWTEST_F(PreferencesXmlUtilsTest, UnnormalReadSettingXml_001, TestSize.Level1) */ HWTEST_F(PreferencesXmlUtilsTest, StringNodeElementTest_001, TestSize.Level1) { - std::string file = "/data/test/test"; + std::string file = "/data/test/test01"; std::remove(file.c_str()); std::vector settings; @@ -131,7 +131,7 @@ HWTEST_F(PreferencesXmlUtilsTest, StringNodeElementTest_001, TestSize.Level1) */ HWTEST_F(PreferencesXmlUtilsTest, ArrayNodeElementTest_001, TestSize.Level1) { - std::string file = "/data/test/test"; + std::string file = "/data/test/test02"; std::remove(file.c_str()); std::vector settings; @@ -170,7 +170,7 @@ HWTEST_F(PreferencesXmlUtilsTest, ArrayNodeElementTest_001, TestSize.Level1) */ HWTEST_F(PreferencesXmlUtilsTest, ArrayNodeElementTest_002, TestSize.Level1) { - std::string file = "/data/test/test"; + std::string file = "/data/test/test03"; std::remove(file.c_str()); std::vector settings; @@ -210,7 +210,7 @@ HWTEST_F(PreferencesXmlUtilsTest, ArrayNodeElementTest_002, TestSize.Level1) */ HWTEST_F(PreferencesXmlUtilsTest, ArrayNodeElementTest_003, TestSize.Level1) { - std::string file = "/data/test/test"; + std::string file = "/data/test/test04"; std::remove(file.c_str()); std::vector settings; diff --git a/relational_store/bundle.json b/relational_store/bundle.json index baeb0a2e..1e2b3fda 100644 --- a/relational_store/bundle.json +++ b/relational_store/bundle.json @@ -140,8 +140,9 @@ ], "test": [ "//foundation/distributeddatamgr/relational_store/test/js/dataability:unittest", - "//foundation/distributeddatamgr/relational_store/test/js/relationalstore/performance:performancetest", + "//foundation/distributeddatamgr/relational_store/test/js/rdb:performancetest", "//foundation/distributeddatamgr/relational_store/test/js/rdb:unittest", + "//foundation/distributeddatamgr/relational_store/test/js/relationalstore:performancetest", "//foundation/distributeddatamgr/relational_store/test/js/relationalstore:unittest", "//foundation/distributeddatamgr/relational_store/test/native/dataability:unittest", "//foundation/distributeddatamgr/relational_store/test/native/rdb:unittest", diff --git a/relational_store/frameworks/js/napi/rdb/BUILD.gn b/relational_store/frameworks/js/napi/rdb/BUILD.gn index 01eb03de..2a91a602 100644 --- a/relational_store/frameworks/js/napi/rdb/BUILD.gn +++ b/relational_store/frameworks/js/napi/rdb/BUILD.gn @@ -79,6 +79,7 @@ ohos_shared_library("napi_rdb") { "ability_runtime:abilitykit_native", "ability_runtime:napi_base_context", "c_utils:utils", + "common_event_service:cesfwk_innerkits", "hilog_native:libhilog", "hitrace_native:hitrace_meter", "napi:ace_napi", diff --git a/relational_store/frameworks/js/napi/rdb/src/napi_rdb_store.cpp b/relational_store/frameworks/js/napi/rdb/src/napi_rdb_store.cpp index 80bb044c..96a498ed 100644 --- a/relational_store/frameworks/js/napi/rdb/src/napi_rdb_store.cpp +++ b/relational_store/frameworks/js/napi/rdb/src/napi_rdb_store.cpp @@ -1115,7 +1115,7 @@ napi_value RdbStoreProxy::SetDistributedTables(napi_env env, napi_callback_info RdbStoreProxy *obj = reinterpret_cast(context->boundObj); int res = obj->rdbStore_->SetDistributedTables(context->tablesName); LOG_DEBUG("RdbStoreProxy::SetDistributedTables res is : %{public}d", res); - return res == E_OK ? OK : ERR; + return (res == E_OK || res == E_NOT_SUPPORTED) ? OK : ERR; }; auto output = [context](napi_env env, napi_value &result) -> int { napi_status status = napi_get_undefined(env, &result); diff --git a/relational_store/frameworks/js/napi/relationalstore/BUILD.gn b/relational_store/frameworks/js/napi/relationalstore/BUILD.gn index 439a34e4..e03667fd 100644 --- a/relational_store/frameworks/js/napi/relationalstore/BUILD.gn +++ b/relational_store/frameworks/js/napi/relationalstore/BUILD.gn @@ -78,6 +78,7 @@ ohos_shared_library("relationalstore") { "ability_runtime:abilitykit_native", "ability_runtime:napi_base_context", "c_utils:utils", + "common_event_service:cesfwk_innerkits", "hilog_native:libhilog", "hitrace_native:hitrace_meter", "napi:ace_napi", diff --git a/relational_store/frameworks/js/napi/relationalstore/include/napi_rdb_error.h b/relational_store/frameworks/js/napi/relationalstore/include/napi_rdb_error.h index 37ba8fd3..ed704e5e 100644 --- a/relational_store/frameworks/js/napi/relationalstore/include/napi_rdb_error.h +++ b/relational_store/frameworks/js/napi/relationalstore/include/napi_rdb_error.h @@ -38,7 +38,7 @@ const static std::map ERROR_MAPS = { { NativeRdb::E_INVALID_FILE_PATH, "Failed to open database by database corrupted" }, { NativeRdb::E_NOT_SUPPORTED, "Capability not supported" }, { E_RESULT_GOTO_ERROR, "The result set is empty or the specified location is invalid." }, - { E_RESULT_GET_ERROR, "The column value is null or the column type is incompatible." }, + { NativeRdb::E_INVALID_STATEMENT, "The column value is null or the column type is incompatible." }, }; #define RDB_REVT_NOTHING diff --git a/relational_store/frameworks/js/napi/relationalstore/include/napi_result_set.h b/relational_store/frameworks/js/napi/relationalstore/include/napi_result_set.h index 65b3bda4..aa3b1d4f 100644 --- a/relational_store/frameworks/js/napi/relationalstore/include/napi_result_set.h +++ b/relational_store/frameworks/js/napi/relationalstore/include/napi_result_set.h @@ -69,6 +69,7 @@ private: static napi_value GetString(napi_env env, napi_callback_info info); static napi_value GetDouble(napi_env env, napi_callback_info info); static napi_value IsColumnNull(napi_env env, napi_callback_info info); + static napi_value GetRow(napi_env env, napi_callback_info info); static napi_value IsClosed(napi_env env, napi_callback_info info); static napi_value GetSharedBlockName(napi_env env, napi_callback_info info); diff --git a/relational_store/frameworks/js/napi/relationalstore/mock/include/napi_result_set.h b/relational_store/frameworks/js/napi/relationalstore/mock/include/napi_result_set.h index a4add516..283e4fd6 100644 --- a/relational_store/frameworks/js/napi/relationalstore/mock/include/napi_result_set.h +++ b/relational_store/frameworks/js/napi/relationalstore/mock/include/napi_result_set.h @@ -66,6 +66,7 @@ private: static napi_value GetString(napi_env env, napi_callback_info info); static napi_value GetDouble(napi_env env, napi_callback_info info); static napi_value IsColumnNull(napi_env env, napi_callback_info info); + static napi_value GetRow(napi_env env, napi_callback_info info); static napi_value IsClosed(napi_env env, napi_callback_info info); static napi_value GetSharedBlockName(napi_env env, napi_callback_info info); diff --git a/relational_store/frameworks/js/napi/relationalstore/src/napi_async_call.cpp b/relational_store/frameworks/js/napi/relationalstore/src/napi_async_call.cpp index 8e970dce..9ec40d65 100644 --- a/relational_store/frameworks/js/napi/relationalstore/src/napi_async_call.cpp +++ b/relational_store/frameworks/js/napi/relationalstore/src/napi_async_call.cpp @@ -75,7 +75,7 @@ void AsyncCall::SetBusinessError(napi_env env, std::shared_ptr error, nap napi_value msg = nullptr; napi_create_object(env, businessError); // if error is not inner error - if (error != nullptr && error->GetCode() != E_INNER_ERROR) { + if (error != nullptr) { napi_create_int32(env, error->GetCode(), &code); napi_create_string_utf8(env, error->GetMessage().c_str(), NAPI_AUTO_LENGTH, &msg); napi_set_named_property(env, *businessError, "code", code); diff --git a/relational_store/frameworks/js/napi/relationalstore/src/napi_result_set.cpp b/relational_store/frameworks/js/napi/relationalstore/src/napi_result_set.cpp index de7a07eb..b2748d96 100644 --- a/relational_store/frameworks/js/napi/relationalstore/src/napi_result_set.cpp +++ b/relational_store/frameworks/js/napi/relationalstore/src/napi_result_set.cpp @@ -16,12 +16,14 @@ #include "napi_result_set.h" #include +#include #include "js_logger.h" #include "js_utils.h" #include "napi_rdb_error.h" #include "napi_rdb_trace.h" #include "rdb_errno.h" +#include "value_object.h" #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) #include "rdb_result_set_bridge.h" @@ -32,6 +34,25 @@ using namespace OHOS::NativeRdb; using namespace OHOS::AppDataMgrJsKit; namespace OHOS { +namespace AppDataMgrJsKit { +namespace JSUtils { +template<> +napi_value Convert2JSValue(napi_env env, const RowEntity &rowEntity) +{ + napi_value ret; + NAPI_CALL(env, napi_create_object(env, &ret)); + std::map values; + rowEntity.Get(values); + napi_value value = nullptr; + for (auto const &it : values) { + value = JSUtils::Convert2JSValue(env, static_cast(it.second)); + NAPI_CALL(env, napi_set_named_property(env, ret, it.first.c_str(), value)); + } + return ret; +} +} +} + namespace RelationalStoreJsKit { static napi_ref __thread ctorRef_ = nullptr; static const int E_OK = 0; @@ -93,6 +114,7 @@ napi_value ResultSetProxy::GetConstructor(napi_env env) DECLARE_NAPI_FUNCTION("getString", GetString), DECLARE_NAPI_FUNCTION("getDouble", GetDouble), DECLARE_NAPI_FUNCTION("isColumnNull", IsColumnNull), + DECLARE_NAPI_FUNCTION("getRow", GetRow), DECLARE_NAPI_GETTER("columnNames", GetAllColumnNames), DECLARE_NAPI_GETTER("columnCount", GetColumnCount), @@ -507,11 +529,22 @@ napi_value ResultSetProxy::IsColumnNull(napi_env env, napi_callback_info info) bool result = false; int errCode = resultSetProxy->resultSet_->IsColumnNull(columnIndex, result); - RDB_NAPI_ASSERT(env, errCode == E_OK, std::make_shared(E_RESULT_GET_ERROR)); + RDB_NAPI_ASSERT(env, errCode == E_OK, std::make_shared(errCode)); return JSUtils::Convert2JSValue(env, result); } +napi_value ResultSetProxy::GetRow(napi_env env, napi_callback_info info) +{ + ResultSetProxy *resultSetProxy = GetInnerResultSet(env, info); + CHECK_RETURN_NULL(resultSetProxy && resultSetProxy->resultSet_); + + RowEntity rowEntity; + int errCode = resultSetProxy->resultSet_->GetRow(rowEntity); + RDB_NAPI_ASSERT(env, errCode == E_OK, std::make_shared(errCode)); + return JSUtils::Convert2JSValue(env, rowEntity); +} + napi_value ResultSetProxy::IsClosed(napi_env env, napi_callback_info info) { ResultSetProxy *resultSetProxy = GetInnerResultSet(env, info); diff --git a/relational_store/frameworks/native/rdb/include/result_set_proxy.h b/relational_store/frameworks/native/rdb/include/result_set_proxy.h index fe57d8d2..60240ab1 100644 --- a/relational_store/frameworks/native/rdb/include/result_set_proxy.h +++ b/relational_store/frameworks/native/rdb/include/result_set_proxy.h @@ -47,6 +47,7 @@ public: int GetLong(int columnIndex, int64_t &value) override; int GetDouble(int columnIndex, double &value) override; int IsColumnNull(int columnIndex, bool &isNull) override; + int GetRow(RowEntity &rowEntity) override; bool IsClosed() const override; int Close() override; diff --git a/relational_store/frameworks/native/rdb/include/sqlite_global_config.h b/relational_store/frameworks/native/rdb/include/sqlite_global_config.h index 21edf315..4138ea18 100644 --- a/relational_store/frameworks/native/rdb/include/sqlite_global_config.h +++ b/relational_store/frameworks/native/rdb/include/sqlite_global_config.h @@ -31,6 +31,7 @@ public: static constexpr int DB_WAL_SIZE_LIMIT = 200 * 1024 * 1024; /* default wal file maximum size : 200M */ static constexpr int WAL_AUTO_CHECKPOINT = 100; /* 100 pages */ static constexpr int APP_DEFAULT_UMASK = 0002; + static constexpr int SQLITE_MAX_COLUMN = 2000; static constexpr char ATTACH_BACKUP_SQL[] = "ATTACH ? AS backup KEY ?"; static constexpr char ATTACH_SQL[] = "ATTACH ? AS ? KEY ?"; static constexpr char EXPORT_SQL[] = "SELECT export_database('backup')"; diff --git a/relational_store/frameworks/native/rdb/mock/include/sqlite_global_config.h b/relational_store/frameworks/native/rdb/mock/include/sqlite_global_config.h index a8b1cf24..08900d55 100644 --- a/relational_store/frameworks/native/rdb/mock/include/sqlite_global_config.h +++ b/relational_store/frameworks/native/rdb/mock/include/sqlite_global_config.h @@ -32,6 +32,7 @@ public: static constexpr int DB_WAL_SIZE_LIMIT = 200 * 1024 * 1024; /* default wal file maximum size : 200M */ static constexpr int WAL_AUTO_CHECKPOINT = 100; /* 100 pages */ static constexpr int APP_DEFAULT_UMASK = 0002; + static constexpr int SQLITE_MAX_COLUMN = 2000; static constexpr char ATTACH_BACKUP_SQL[] = "ATTACH ? AS backup KEY ?"; static constexpr char ATTACH_SQL[] = "ATTACH ? AS ? KEY ?"; static constexpr char EXPORT_SQL[] = "SELECT export_database('backup')"; diff --git a/relational_store/frameworks/native/rdb/src/abs_result_set.cpp b/relational_store/frameworks/native/rdb/src/abs_result_set.cpp index b7c7fc1a..1840a7a3 100644 --- a/relational_store/frameworks/native/rdb/src/abs_result_set.cpp +++ b/relational_store/frameworks/native/rdb/src/abs_result_set.cpp @@ -24,6 +24,40 @@ namespace OHOS { namespace NativeRdb { +void RowEntity::Put(const std::string &name, const ValueObject &value) +{ + auto it = values_.emplace(name, std::move(value)); + indexs_.push_back(it.first); +} + +ValueObject RowEntity::Get(const std::string &name) const +{ + auto it = values_.find(name); + if (it == values_.end()) { + return ValueObject(); + } + return it->second; +} + +ValueObject RowEntity::Get(int index) const +{ + if (index < 0 || index >= indexs_.size()) { + return ValueObject(); + } + return indexs_[index]->second; +} + +void RowEntity::Get(std::map &outValues) const +{ + outValues = values_; +} + +void RowEntity::Clear() +{ + values_.clear(); + indexs_.clear(); +} + AbsResultSet::AbsResultSet() : rowPos_(INIT_POS), isClosed(false) { } @@ -70,6 +104,61 @@ int AbsResultSet::IsColumnNull(int columnIndex, bool &isNull) return E_OK; } +int AbsResultSet::GetRow(RowEntity &rowEntity) +{ + rowEntity.Clear(); + std::vector columnNames; + int ret = GetAllColumnNames(columnNames); + if (ret != E_OK) { + LOG_ERROR("GetAllColumnNames::ret is %{public}d", ret); + return ret; + } + int columnCount = static_cast(columnNames.size()); + + ColumnType columnType; + for (int columnIndex = 0; columnIndex < columnCount; ++columnIndex) { + ret = GetColumnType(columnIndex, columnType); + if (ret != E_OK) { + LOG_ERROR("GetColumnType::ret is %{public}d", ret); + return ret; + } + switch (columnType) { + case ColumnType::TYPE_NULL: { + rowEntity.Put(columnNames[columnIndex], ValueObject()); + break; + } + case ColumnType::TYPE_INTEGER: { + int64_t value; + GetLong(columnIndex, value); + rowEntity.Put(columnNames[columnIndex], ValueObject(value)); + break; + } + case ColumnType::TYPE_FLOAT: { + double value; + GetDouble(columnIndex, value); + rowEntity.Put(columnNames[columnIndex], ValueObject(value)); + break; + } + case ColumnType::TYPE_STRING: { + std::string value; + GetString(columnIndex, value); + rowEntity.Put(columnNames[columnIndex], ValueObject(value)); + break; + } + case ColumnType::TYPE_BLOB: { + std::vector value; + GetBlob(columnIndex, value); + rowEntity.Put(columnNames[columnIndex], ValueObject(value)); + break; + } + default: { + return E_ERROR; + } + } + } + return E_OK; +} + int AbsResultSet::GoToRow(int position) { return E_OK; diff --git a/relational_store/frameworks/native/rdb/src/rdb_store_impl.cpp b/relational_store/frameworks/native/rdb/src/rdb_store_impl.cpp index 68d48dc0..179e4de9 100644 --- a/relational_store/frameworks/native/rdb/src/rdb_store_impl.cpp +++ b/relational_store/frameworks/native/rdb/src/rdb_store_impl.cpp @@ -1118,10 +1118,10 @@ std::string RdbStoreImpl::ObtainDistributedTableName(const std::string &device, return ""; } -// auto translateCall = [uuid](const std::string &oriDevId, const DistributedDB::StoreInfo &info) { -// return uuid; -// }; -// DistributedDB::RuntimeConfig::SetTranslateToDeviceIdCallback(translateCall); + auto translateCall = [uuid](const std::string &oriDevId, const DistributedDB::StoreInfo &info) { + return uuid; + }; + DistributedDB::RuntimeConfig::SetTranslateToDeviceIdCallback(translateCall); return DistributedDB::RelationalStoreManager::GetDistributedTableName(uuid, table); } diff --git a/relational_store/frameworks/native/rdb/src/rdb_store_manager.cpp b/relational_store/frameworks/native/rdb/src/rdb_store_manager.cpp index a5e8bb47..86b51373 100644 --- a/relational_store/frameworks/native/rdb/src/rdb_store_manager.cpp +++ b/relational_store/frameworks/native/rdb/src/rdb_store_manager.cpp @@ -28,7 +28,7 @@ namespace OHOS { namespace NativeRdb { -RdbStoreNode::RdbStoreNode(const std::shared_ptr &rdbStore) : rdbStore_(rdbStore) {} +RdbStoreNode::RdbStoreNode(const std::shared_ptr &rdbStore) : rdbStore_(rdbStore), timerId_(0) {} RdbStoreNode &RdbStoreNode::operator=(const std::shared_ptr &store) { diff --git a/relational_store/frameworks/native/rdb/src/result_set_proxy.cpp b/relational_store/frameworks/native/rdb/src/result_set_proxy.cpp index 91558f05..1dfdb580 100644 --- a/relational_store/frameworks/native/rdb/src/result_set_proxy.cpp +++ b/relational_store/frameworks/native/rdb/src/result_set_proxy.cpp @@ -239,6 +239,11 @@ int ResultSetProxy::IsColumnNull(int columnIndex, bool &isNull) return E_OK; } +int ResultSetProxy::GetRow(RowEntity &rowEntity) +{ + return E_NOT_SUPPORT; +} + bool ResultSetProxy::IsClosed() const { MessageParcel data, reply; diff --git a/relational_store/frameworks/native/rdb/src/store_session.cpp b/relational_store/frameworks/native/rdb/src/store_session.cpp new file mode 100644 index 00000000..312a822c --- /dev/null +++ b/relational_store/frameworks/native/rdb/src/store_session.cpp @@ -0,0 +1,447 @@ +/* + * 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 "store_session.h" +#include +#include +#include +#include "logger.h" +#include "rdb_errno.h" +#if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) +#include "shared_block.h" +#endif +#include "sqlite_database_utils.h" +#include "sqlite_utils.h" +#include "base_transaction.h" + +namespace OHOS::NativeRdb { +StoreSession::StoreSession(SqliteConnectionPool &connectionPool) + : connectionPool(connectionPool), readConnection(nullptr), connection(nullptr), + readConnectionUseCount(0), connectionUseCount(0), isInStepQuery(false) +{ +} + +StoreSession::~StoreSession() +{ +} + +void StoreSession::AcquireConnection(bool isReadOnly) +{ + if (isReadOnly) { + if (readConnection == nullptr) { + readConnection = connectionPool.AcquireConnection(true); + } + readConnectionUseCount += 1; + return; + } + if (connection == nullptr) { + connection = connectionPool.AcquireConnection(false); + } + connectionUseCount += 1; + return; +} + +void StoreSession::ReleaseConnection(bool isReadOnly) +{ + if (isReadOnly) { + if ((readConnection == nullptr) || (readConnectionUseCount <= 0)) { + LOG_ERROR("SQLiteSession ReleaseConnection repeated release"); + return; + } + if (--readConnectionUseCount == 0) { + connectionPool.ReleaseConnection(readConnection); + readConnection = nullptr; + } + return; + } + if ((connection == nullptr) || (connectionUseCount <= 0)) { + LOG_ERROR("SQLiteSession ReleaseConnection repeated release"); + return; + } + + if (--connectionUseCount == 0) { + connectionPool.ReleaseConnection(connection); + connection = nullptr; + } +} + +int StoreSession::PrepareAndGetInfo( + const std::string &sql, bool &outIsReadOnly, int &numParameters, std::vector &columnNames) +{ + // Obtains the type of SQL statement. + int type = SqliteUtils::GetSqlStatementType(sql); + if (SqliteUtils::IsSpecial(type)) { + return E_TRANSACTION_IN_EXECUTE; + } + bool assumeReadOnly = SqliteUtils::IsSqlReadOnly(type); + AcquireConnection(assumeReadOnly); + auto con = assumeReadOnly ? readConnection : connection; + int errCode = con->PrepareAndGetInfo(sql, outIsReadOnly, numParameters, columnNames); + if (errCode != 0) { + ReleaseConnection(assumeReadOnly); + return errCode; + } + + ReleaseConnection(assumeReadOnly); + return E_OK; +} + +int StoreSession::BeginExecuteSql(const std::string &sql, bool &isReadOnly) +{ + int type = SqliteUtils::GetSqlStatementType(sql); + if (SqliteUtils::IsSpecial(type)) { + return E_TRANSACTION_IN_EXECUTE; + } + + bool assumeReadOnly = SqliteUtils::IsSqlReadOnly(type); + AcquireConnection(assumeReadOnly); + SqliteConnection *con = assumeReadOnly ? readConnection : connection; + int errCode = con->Prepare(sql, isReadOnly); + if (errCode != 0) { + ReleaseConnection(assumeReadOnly); + return errCode; + } + isReadOnly = assumeReadOnly; + return E_OK; +} +int StoreSession::ExecuteSql(const std::string &sql, const std::vector &bindArgs) +{ + bool isReadOnly = false; + int errCode = BeginExecuteSql(sql, isReadOnly); + if (errCode != 0) { + return errCode; + } + SqliteConnection *con = isReadOnly ? readConnection : connection; + errCode = con->ExecuteSql(sql, bindArgs); + ReleaseConnection(isReadOnly); + return errCode; +} + +int StoreSession::ExecuteForChangedRowCount( + int &changedRows, const std::string &sql, const std::vector &bindArgs) +{ + bool isReadOnly = false; + int errCode = BeginExecuteSql(sql, isReadOnly); + if (errCode != 0) { + return errCode; + } + auto con = isReadOnly ? readConnection : connection; + errCode = con->ExecuteForChangedRowCount(changedRows, sql, bindArgs); + ReleaseConnection(isReadOnly); + return errCode; +} + +int StoreSession::ExecuteForLastInsertedRowId( + int64_t &outRowId, const std::string &sql, const std::vector &bindArgs) +{ + bool isReadOnly = false; + int errCode = BeginExecuteSql(sql, isReadOnly); + if (errCode != 0) { + LOG_ERROR("rdbStore BeginExecuteSql failed"); + return errCode; + } + auto con = isReadOnly ? readConnection : connection; + errCode = con->ExecuteForLastInsertedRowId(outRowId, sql, bindArgs); + if (errCode != E_OK) { + LOG_ERROR("rdbStore ExecuteForLastInsertedRowId FAILED"); + } + ReleaseConnection(isReadOnly); + return errCode; +} + +int StoreSession::ExecuteGetLong(int64_t &outValue, const std::string &sql, const std::vector &bindArgs) +{ + bool isReadOnly = false; + int errCode = BeginExecuteSql(sql, isReadOnly); + if (errCode != 0) { + return errCode; + } + auto con = isReadOnly ? readConnection : connection; + errCode = con->ExecuteGetLong(outValue, sql, bindArgs); + ReleaseConnection(isReadOnly); + return errCode; +} + +int StoreSession::ExecuteGetString( + std::string &outValue, const std::string &sql, const std::vector &bindArgs) +{ + bool isReadOnly = false; + int errCode = BeginExecuteSql(sql, isReadOnly); + if (errCode != 0) { + return errCode; + } + auto con = isReadOnly ? readConnection : connection; + std::string sqlstr = sql; + int type = SqliteDatabaseUtils::GetSqlStatementType(sqlstr); + if (type == STATEMENT_PRAGMA) { + ReleaseConnection(isReadOnly); + AcquireConnection(false); + con = connection; + } + + errCode = con->ExecuteGetString(outValue, sql, bindArgs); + ReleaseConnection(isReadOnly); + return errCode; +} + +int StoreSession::Backup(const std::string databasePath, const std::vector destEncryptKey) +{ + std::vector bindArgs; + bindArgs.push_back(ValueObject(databasePath)); + if (destEncryptKey.size() != 0) { + bindArgs.push_back(ValueObject(destEncryptKey)); + } else { + std::string str = ""; + bindArgs.push_back(ValueObject(str)); + } + + int errCode = ExecuteSql(ATTACH_BACKUP_SQL, bindArgs); + if (errCode != E_OK) { + LOG_ERROR("ExecuteSql ATTACH_BACKUP_SQL error %{public}d", errCode); + return errCode; + } + int64_t count; + errCode = ExecuteGetLong(count, EXPORT_SQL, std::vector()); + if (errCode != E_OK) { + LOG_ERROR("ExecuteSql EXPORT_SQL error %{public}d", errCode); + return errCode; + } + + errCode = ExecuteSql(DETACH_BACKUP_SQL, std::vector()); + if (errCode != E_OK) { + LOG_ERROR("ExecuteSql DETACH_BACKUP_SQL error %{public}d", errCode); + return errCode; + } + return E_OK; +} + +// Checks whether this thread holds a database connection. +bool StoreSession::IsHoldingConnection() const +{ + if (connection == nullptr && readConnection == nullptr) { + return false; + } else { + return true; + } +} + +int StoreSession::CheckNoTransaction() const +{ + int errorCode = 0; + if (connectionPool.getTransactionStack().empty()) { + errorCode = E_STORE_SESSION_NO_CURRENT_TRANSACTION; + return errorCode; + } + return E_OK; +} + +int StoreSession::GiveConnectionTemporarily(int64_t milliseconds) +{ + int errorCode = CheckNoTransaction(); + if (errorCode != E_OK) { + return errorCode; + } + BaseTransaction transaction = connectionPool.getTransactionStack().top(); + if (transaction.IsMarkedSuccessful() || connectionPool.getTransactionStack().size() > 1) { + errorCode = E_STORE_SESSION_NOT_GIVE_CONNECTION_TEMPORARILY; + return errorCode; + } + + if (milliseconds > 0) { + std::this_thread::sleep_for(std::chrono::milliseconds(milliseconds)); + } + BeginTransaction(); + return E_OK; +} + +int StoreSession::Attach( + const std::string &alias, const std::string &pathName, const std::vector destEncryptKey) +{ + std::string journalMode; + int errCode = ExecuteGetString(journalMode, "PRAGMA journal_mode", std::vector()); + if (errCode != E_OK) { + LOG_ERROR("RdbStoreImpl CheckAttach fail to get journal mode : %{public}d", errCode); + return errCode; + } + journalMode = SqliteUtils::StrToUpper(journalMode); + if (journalMode == "WAL") { + LOG_ERROR("RdbStoreImpl attach is not supported in WAL mode"); + return E_NOT_SUPPORTED_ATTACH_IN_WAL_MODE; + } + + std::vector bindArgs; + bindArgs.push_back(ValueObject(pathName)); + bindArgs.push_back(ValueObject(alias)); + if (destEncryptKey.size() != 0) { + bindArgs.push_back(ValueObject(destEncryptKey)); + } else { + std::string str = ""; + bindArgs.push_back(ValueObject(str)); + } + errCode = ExecuteSql(ATTACH_SQL, bindArgs); + if (errCode != E_OK) { + LOG_ERROR("ExecuteSql ATTACH_SQL error %{public}d", errCode); + return errCode; + } + + return E_OK; +} + +int StoreSession::BeginTransaction(TransactionObserver *transactionObserver) +{ + if (connectionPool.getTransactionStack().empty()) { + AcquireConnection(false); + + int errCode = connection->ExecuteSql("BEGIN EXCLUSIVE;"); + if (errCode != E_OK) { + ReleaseConnection(false); + return errCode; + } + } + + if (transactionObserver != nullptr) { + transactionObserver->OnBegin(); + } + + BaseTransaction transaction(connectionPool.getTransactionStack().size()); + connectionPool.getTransactionStack().push(transaction); + + return E_OK; +} + +bool StoreSession::IsInTransaction() const +{ + return !connectionPool.getTransactionStack().empty(); +} + +std::shared_ptr StoreSession::BeginStepQuery( + int &errCode, const std::string &sql, const std::vector &selectionArgs) +{ + if (isInStepQuery == true) { + LOG_ERROR("StoreSession BeginStepQuery fail : begin more step query in one session !"); + errCode = E_MORE_STEP_QUERY_IN_ONE_SESSION; + return nullptr; // fail,already in + } + + if (SqliteUtils::GetSqlStatementType(sql) != SqliteUtils::STATEMENT_SELECT) { + LOG_ERROR("StoreSession BeginStepQuery fail : not select sql !"); + errCode = E_EXECUTE_IN_STEP_QUERY; + return nullptr; + } + + AcquireConnection(true); + std::shared_ptr statement = readConnection->BeginStepQuery(errCode, sql, selectionArgs); + if (statement == nullptr) { + ReleaseConnection(true); + return nullptr; + } + isInStepQuery = true; + return statement; +} + +int StoreSession::EndStepQuery() +{ + if (isInStepQuery == false) { + return E_OK; + } + + int errCode = readConnection->EndStepQuery(); + isInStepQuery = false; + ReleaseConnection(true); + return errCode; +} + +#if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) +int StoreSession::ExecuteForSharedBlock(int &rowNum, std::string sql, const std::vector &bindArgs, + AppDataFwk::SharedBlock *sharedBlock, int startPos, int requiredPos, bool isCountAllRows) +{ + bool isReadOnly = false; + int errCode = BeginExecuteSql(sql, isReadOnly); + if (errCode != E_OK) { + return errCode; + } + SqliteConnection *con = isReadOnly ? readConnection : connection; + errCode = + con->ExecuteForSharedBlock(rowNum, sql, bindArgs, sharedBlock, startPos, requiredPos, isCountAllRows); + ReleaseConnection(isReadOnly); + return errCode; +} +#endif + +int StoreSession::BeginTransaction() +{ + AcquireConnection(false); + + BaseTransaction transaction(connectionPool.getTransactionStack().size()); + int errCode = connection->ExecuteSql(transaction.GetTransactionStr()); + if (errCode != E_OK) { + LOG_DEBUG("storeSession BeginTransaction Failed"); + ReleaseConnection(false); + return errCode; + } + connectionPool.getTransactionStack().push(transaction); + ReleaseConnection(false); + return E_OK; +} + +int StoreSession::Commit() +{ + if (connectionPool.getTransactionStack().empty()) { + return E_OK; + } + BaseTransaction transaction = connectionPool.getTransactionStack().top(); + std::string sqlStr = transaction.GetCommitStr(); + if (sqlStr.size() <= 1) { + connectionPool.getTransactionStack().pop(); + return E_OK; + } + + AcquireConnection(false); + int errCode = connection->ExecuteSql(sqlStr); + ReleaseConnection(false); + if (errCode != E_OK) { + // if error the transaction is leaving for rollback + return errCode; + } + connectionPool.getTransactionStack().pop(); + return E_OK; +} + +int StoreSession::RollBack() +{ + std::stack transactionStack = connectionPool.getTransactionStack(); + if (transactionStack.empty()) { + return E_NO_TRANSACTION_IN_SESSION; + } + BaseTransaction transaction = transactionStack.top(); + transactionStack.pop(); + if (transaction.GetType() != TransType::ROLLBACK_SELF && !transactionStack.empty()) { + transactionStack.top().SetChildFailure(true); + } + AcquireConnection(false); + int errCode = connection->ExecuteSql(transaction.GetRollbackStr()); + ReleaseConnection(false); + if (errCode != E_OK) { + LOG_ERROR("storeSession RollBack Fail"); + } + + return errCode; +} + +int StoreSession::GetConnectionUseCount() +{ + return connectionUseCount; +} +} // namespace OHOS::NativeRdb diff --git a/relational_store/interfaces/inner_api/rdb/include/abs_result_set.h b/relational_store/interfaces/inner_api/rdb/include/abs_result_set.h index 708337ff..9f0011fe 100644 --- a/relational_store/interfaces/inner_api/rdb/include/abs_result_set.h +++ b/relational_store/interfaces/inner_api/rdb/include/abs_result_set.h @@ -22,6 +22,7 @@ #include #include "result_set.h" +#include "value_object.h" namespace OHOS { namespace NativeRdb { @@ -121,6 +122,11 @@ public: */ RDB_API_EXPORT int IsColumnNull(int columnIndex, bool &isNull) override; + /** + * @brief Gets the entire row of data for the current row from the result set. + */ + RDB_API_EXPORT int GetRow(RowEntity &rowEntity) override; + /** * @brief Move the cursor to an absolute position. * diff --git a/relational_store/interfaces/inner_api/rdb/include/rdb_errno.h b/relational_store/interfaces/inner_api/rdb/include/rdb_errno.h index 7f89c41c..113dd598 100644 --- a/relational_store/interfaces/inner_api/rdb/include/rdb_errno.h +++ b/relational_store/interfaces/inner_api/rdb/include/rdb_errno.h @@ -60,9 +60,9 @@ constexpr int E_EMPTY_TABLE_NAME = (E_BASE + 5); constexpr int E_EMPTY_VALUES_BUCKET = (E_BASE + 6); /** -* @brief The error code for the current status is invalid. +* @brief The error code when the sql is not select. */ -constexpr int E_INVALID_STATEMENT = (E_BASE + 7); +constexpr int E_EXECUTE_IN_STEP_QUERY = (E_BASE + 7); /** * @brief The error code for the column index is invalid. @@ -90,9 +90,9 @@ constexpr int E_INVALID_FILE_PATH = (E_BASE + 11); constexpr int E_TRANSACTION_IN_EXECUTE = (E_BASE + 12); /** -* @brief The error code when the sql is not select. +* @brief The error code for the current status is invalid. */ -constexpr int E_EXECUTE_IN_STEP_QUERY = (E_BASE + 13); +constexpr int E_INVALID_STATEMENT = (E_BASE + 13); /** * @brief The error code when execute write operation in read connection. diff --git a/relational_store/interfaces/inner_api/rdb/include/remote_result_set.h b/relational_store/interfaces/inner_api/rdb/include/remote_result_set.h new file mode 100644 index 00000000..e32ac243 --- /dev/null +++ b/relational_store/interfaces/inner_api/rdb/include/remote_result_set.h @@ -0,0 +1,304 @@ +/* + * 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_REMOTE_RESULT_SET_H +#define NATIVE_RDB_REMOTE_RESULT_SET_H + +#include +#include +#include "rdb_visibility.h" + +namespace OHOS { +namespace NativeRdb { + +/** + * @brief Indicates the column type. + * + * Value returned by getColumnType(int) + */ +enum class ColumnType { + /** Indicates the column type is NULL.*/ + TYPE_NULL = 0, + /** Indicates the column type is INTEGER.*/ + TYPE_INTEGER, + /** Indicates the column type is FLOAT.*/ + TYPE_FLOAT, + /** Indicates the column type is STRING.*/ + TYPE_STRING, + /** Indicates the column type is BLOB.*/ + TYPE_BLOB, +}; + +/** + * The RemoteResultSet class of RDB. + * Provides methods for accessing a database result set generated by remote query the database. + */ +class RDB_API_EXPORT RemoteResultSet { +public: + /** + * @brief The error CMD in the correct case. + */ + enum { + /** Indicates the current CMD is CMD_GET_ALL_COLUMN_NAMES.*/ + CMD_GET_ALL_COLUMN_NAMES, + /** Indicates the current CMD is CMD_GET_COLUMN_COUNT.*/ + CMD_GET_COLUMN_COUNT, + /** Indicates the current CMD is CMD_GET_COLUMN_TYPE.*/ + CMD_GET_COLUMN_TYPE, + /** Indicates the current CMD is CMD_GET_COLUMN_INDEX.*/ + CMD_GET_COLUMN_INDEX, + /** Indicates the current CMD is CMD_GET_COLUMN_NAME.*/ + CMD_GET_COLUMN_NAME, + /** Indicates the current CMD is CMD_GET_ROW_COUNT.*/ + CMD_GET_ROW_COUNT, + /** Indicates the current CMD is CMD_GET_ROW_INDEX.*/ + CMD_GET_ROW_INDEX, + /** Indicates the current CMD is CMD_GO_TO.*/ + CMD_GO_TO, + /** Indicates the current CMD is CMD_GO_TO_ROW.*/ + CMD_GO_TO_ROW, + /** Indicates the current CMD is CMD_GO_TO_FIRST_ROW.*/ + CMD_GO_TO_FIRST_ROW, + /** Indicates the current CMD is CMD_GO_TO_LAST_ROW.*/ + CMD_GO_TO_LAST_ROW, + /** Indicates the current CMD is CMD_GO_TO_NEXT_ROW.*/ + CMD_GO_TO_NEXT_ROW, + /** Indicates the current CMD is CMD_GO_TO_PREV_ROW.*/ + CMD_GO_TO_PREV_ROW, + /** Indicates the current CMD is CMD_IS_ENDED_ROW.*/ + CMD_IS_ENDED_ROW, + /** Indicates the current CMD is CMD_IS_STARTED_ROW.*/ + CMD_IS_STARTED_ROW, + /** Indicates the current CMD is CMD_IS_AT_FIRST_ROW.*/ + CMD_IS_AT_FIRST_ROW, + /** Indicates the current CMD is CMD_IS_AT_LAST_ROW.*/ + CMD_IS_AT_LAST_ROW, + /** Indicates the current CMD is CMD_GET_BLOB.*/ + CMD_GET_BLOB, + /** Indicates the current CMD is CMD_GET_STRING.*/ + CMD_GET_STRING, + /** Indicates the current CMD is CMD_GET_INT.*/ + CMD_GET_INT, + /** Indicates the current CMD is CMD_GET_LONG.*/ + CMD_GET_LONG, + /** Indicates the current CMD is CMD_GET_DOUBLE.*/ + CMD_GET_DOUBLE, + /** Indicates the current CMD is CMD_IS_COLUMN_NULL.*/ + CMD_IS_COLUMN_NULL, + /** Indicates the current CMD is CMD_IS_CLOSED.*/ + CMD_IS_CLOSED, + /** Indicates the current CMD is CMD_CLOSE.*/ + CMD_CLOSE, + /** Indicates the current CMD is CMD_MAX.*/ + CMD_MAX + }; + + /** + * @brief Destructor. + */ + virtual ~RemoteResultSet() {} + + /** + * @brief Obtains a string array holding the names of all of the columns in the result set. + * + * @return Returns the names of the columns contains in this query result. + */ + virtual int GetAllColumnNames(std::vector &columnNames) = 0; + + /** + * @brief Obtains the total number of columns. + * + * @return Returns the number of columns + */ + virtual int GetColumnCount(int &count) = 0; + + /** + * @brief Obtains data type of the given column's value. + * + * @param columnIndex Indicates the zero-based index of the target column. + * @return Returns column value type. + */ + virtual int GetColumnType(int columnIndex, ColumnType &columnType) = 0; + + /** + * @brief Obtains the zero-based index for the given column name. + * + * @param columnName Indicates the name of the column. + * @return Returns the column index for the given column, or -1 if the column does not exist. + */ + virtual int GetColumnIndex(const std::string &columnName, int &columnIndex) = 0; + + /** + * @brief Obtains the column name at the given column index. + * + * @param columnIndex Indicates the zero-based index. + * @return Returns the column name for the given index. + */ + virtual int GetColumnName(int columnIndex, std::string &columnName) = 0; + + /** + * @brief Obtains the numbers of rows in the result set. + */ + virtual int GetRowCount(int &count) = 0; + + /** + * @brief Obtains the current position of the cursor in the result set. + * + * The value is zero-based. When the result set is first returned the cursor + * will be at position -1, which is before the first row. + * After the last row is returned another call to next() will leave the cursor past + * the last entry, at a position of count(). + * + * @return Returns the current cursor position. + */ + virtual int GetRowIndex(int &position) const = 0; + + /** + * @brief Move the cursor a relative amount from current position. Positive offset move forward, + * negative offset move backward. + * + * @param offset Indicates the offset to be applied from the current position. + * @return Returns whether the requested move succeeded. + */ + virtual int GoTo(int offset) = 0; + + /** + * @brief Move the cursor to an absolute position. + * + * @param position Indicates the zero-based position to move to. + * @return Returns whether the requested move succeeded. + */ + virtual int GoToRow(int position) = 0; + + /** + * @brief Move the cursor to the first row. + * + * @return Returns whether the requested move succeeded. + */ + virtual int GoToFirstRow() = 0; + + /** + * @brief Move the cursor to the last row. + * + * @return Returns whether the requested move succeeded. + */ + virtual int GoToLastRow() = 0; + + /** + * @brief Move the cursor to the next row. + * + * @return Returns whether the requested move succeeded. + */ + virtual int GoToNextRow() = 0; + + /** + * @brief Move the cursor to the previous row. + * + * @return Returns whether the requested move succeeded. + */ + virtual int GoToPreviousRow() = 0; + + /** + * @brief Obtains whether the cursor is pointing to the position after the last row. + * + * @return Returns whether the cursor is after the last row. + */ + virtual int IsEnded(bool &result) = 0; + + /** + * @brief Obtains whether the cursor is pointing to the position before the first row. + * + * @return Returns whether the cursor is before the first row. + */ + virtual int IsStarted(bool &result) const = 0; + + /** + * @brief Obtains whether the cursor is pointing to the first row. + * + * @return Returns whether the cursor is pointing at the first entry. + */ + virtual int IsAtFirstRow(bool &result) const = 0; + + /** + * @brief Obtains whether the cursor is pointing to the last row. + * + * @return Returns whether the cursor is pointing at the last entry. + */ + virtual int IsAtLastRow(bool &result) = 0; + + /** + * @brief Obtains the value of the requested column as a byte array. + * + * @param columnIndex Indicates the zero-based index of the target column. + * @return Returns the value of the requested column as a byte array. + */ + virtual int GetBlob(int columnIndex, std::vector &blob) = 0; + + /** + * @brief Obtains the value of the requested column as a String. + * + * @param columnIndex Indicates the zero-based index of the target column. + * @return Returns the value of the requested column as a String. + */ + virtual int GetString(int columnIndex, std::string &value) = 0; + + /** + * @brief Obtains the value of the requested column as a int. + * + * @param columnIndex Indicates the zero-based index of the target column. + * @return Returns the value of the requested column as a int. + */ + virtual int GetInt(int columnIndex, int &value) = 0; + + /** + * @brief Obtains the value of the requested column as a long. + * + * @param columnIndex Indicates the zero-based index of the target column. + * @return Returns the value of the requested column as a long. + */ + virtual int GetLong(int columnIndex, int64_t &value) = 0; + + /** + * @brief Obtains the value of the requested column as a double. + * + * @param columnIndex Indicates the zero-based index of the target column. + * @return Returns the value of the requested column as a double. + */ + virtual int GetDouble(int columnIndex, double &value) = 0; + + /** + * @brief Obtains Whether the value of the requested column is null. + * + * @param columnIndex Indicates the zero-based index of the target column. + * @return Returns whether the column value is null. + */ + virtual int IsColumnNull(int columnIndex, bool &isNull) = 0; + + /** + * @brief Obtains Return true if the result set is closed. + * + * @return Returns true if the result set is closed. + */ + virtual bool IsClosed() const = 0; + + /** + * @brief Closes the result set, releasing all of its resources and making it completely invalid. + */ + virtual int Close() = 0; +}; + +} // namespace NativeRdb +} // namespace OHOS +#endif diff --git a/relational_store/interfaces/inner_api/rdb/include/result_set.h b/relational_store/interfaces/inner_api/rdb/include/result_set.h index 2a7f02a7..ff08b21f 100644 --- a/relational_store/interfaces/inner_api/rdb/include/result_set.h +++ b/relational_store/interfaces/inner_api/rdb/include/result_set.h @@ -18,284 +18,39 @@ #include #include -#include "rdb_visibility.h" +#include +#include "remote_result_set.h" +#include "value_object.h" + namespace OHOS { namespace NativeRdb { - -/** - * @brief Indicates the column type. - * - * Value returned by getColumnType(int) - */ -enum class ColumnType { - /** Indicates the column type is NULL.*/ - TYPE_NULL = 0, - /** Indicates the column type is INTEGER.*/ - TYPE_INTEGER, - /** Indicates the column type is FLOAT.*/ - TYPE_FLOAT, - /** Indicates the column type is STRING.*/ - TYPE_STRING, - /** Indicates the column type is BLOB.*/ - TYPE_BLOB, +struct RDB_API_EXPORT RowEntity { +public: + RDB_API_EXPORT void Put(const std::string &name, const ValueObject &value); + RDB_API_EXPORT ValueObject Get(const std::string &name) const; + RDB_API_EXPORT ValueObject Get(const int index) const; + RDB_API_EXPORT void Get(std::map &outValues) const; + RDB_API_EXPORT void Clear(); +private: + std::map values_; + std::vector indexs_; }; /** * The ResultSet class of RDB. * Provides methods for accessing a database result set generated by querying the database. */ -class RDB_API_EXPORT ResultSet { +class RDB_API_EXPORT ResultSet : public RemoteResultSet { public: - /** - * @brief The error CMD in the correct case. - */ - enum { - /** Indicates the current error CMD is CMD_GET_ALL_COLUMN_NAMES.*/ - CMD_GET_ALL_COLUMN_NAMES, - /** Indicates the current error CMD is CMD_GET_COLUMN_COUNT.*/ - CMD_GET_COLUMN_COUNT, - /** Indicates the current error CMD is CMD_GET_COLUMN_TYPE.*/ - CMD_GET_COLUMN_TYPE, - /** Indicates the current error CMD is CMD_GET_COLUMN_INDEX.*/ - CMD_GET_COLUMN_INDEX, - /** Indicates the current error CMD is CMD_GET_COLUMN_NAME.*/ - CMD_GET_COLUMN_NAME, - /** Indicates the current error CMD is CMD_GET_ROW_COUNT.*/ - CMD_GET_ROW_COUNT, - /** Indicates the current error CMD is CMD_GET_ROW_INDEX.*/ - CMD_GET_ROW_INDEX, - /** Indicates the current error CMD is CMD_GO_TO.*/ - CMD_GO_TO, - /** Indicates the current error CMD is CMD_GO_TO_ROW.*/ - CMD_GO_TO_ROW, - /** Indicates the current error CMD is CMD_GO_TO_FIRST_ROW.*/ - CMD_GO_TO_FIRST_ROW, - /** Indicates the current error CMD is CMD_GO_TO_LAST_ROW.*/ - CMD_GO_TO_LAST_ROW, - /** Indicates the current error CMD is CMD_GO_TO_NEXT_ROW.*/ - CMD_GO_TO_NEXT_ROW, - /** Indicates the current error CMD is CMD_GO_TO_PREV_ROW.*/ - CMD_GO_TO_PREV_ROW, - /** Indicates the current error CMD is CMD_IS_ENDED_ROW.*/ - CMD_IS_ENDED_ROW, - /** Indicates the current error CMD is CMD_IS_STARTED_ROW.*/ - CMD_IS_STARTED_ROW, - /** Indicates the current error CMD is CMD_IS_AT_FIRST_ROW.*/ - CMD_IS_AT_FIRST_ROW, - /** Indicates the current error CMD is CMD_IS_AT_LAST_ROW.*/ - CMD_IS_AT_LAST_ROW, - /** Indicates the current error CMD is CMD_GET_BLOB.*/ - CMD_GET_BLOB, - /** Indicates the current error CMD is CMD_GET_STRING.*/ - CMD_GET_STRING, - /** Indicates the current error CMD is CMD_GET_INT.*/ - CMD_GET_INT, - /** Indicates the current error CMD is CMD_GET_LONG.*/ - CMD_GET_LONG, - /** Indicates the current error CMD is CMD_GET_DOUBLE.*/ - CMD_GET_DOUBLE, - /** Indicates the current error CMD is CMD_IS_COLUMN_NULL.*/ - CMD_IS_COLUMN_NULL, - /** Indicates the current error CMD is CMD_IS_CLOSED.*/ - CMD_IS_CLOSED, - /** Indicates the current error CMD is CMD_CLOSE.*/ - CMD_CLOSE, - /** Indicates the current error CMD is CMD_MAX.*/ - CMD_MAX - }; - /** * @brief Destructor. */ virtual ~ResultSet() {} /** - * @brief Obtains a string array holding the names of all of the columns in the result set. - * - * @return Returns the names of the columns contains in this query result. - */ - virtual int GetAllColumnNames(std::vector &columnNames) = 0; - - /** - * @brief Obtains the total number of columns. - * - * @return Returns the number of columns - */ - virtual int GetColumnCount(int &count) = 0; - - /** - * @brief Obtains data type of the given column's value. - * - * @param columnIndex Indicates the zero-based index of the target column. - * @return Returns column value type. - */ - virtual int GetColumnType(int columnIndex, ColumnType &columnType) = 0; - - /** - * @brief Obtains the zero-based index for the given column name. - * - * @param columnName Indicates the name of the column. - * @return Returns the column index for the given column, or -1 if the column does not exist. - */ - virtual int GetColumnIndex(const std::string &columnName, int &columnIndex) = 0; - - /** - * @brief Obtains the column name at the given column index. - * - * @param columnIndex Indicates the zero-based index. - * @return Returns the column name for the given index. - */ - virtual int GetColumnName(int columnIndex, std::string &columnName) = 0; - - /** - * @brief Obtains the numbers of rows in the result set. - */ - virtual int GetRowCount(int &count) = 0; - - /** - * @brief Obtains the current position of the cursor in the result set. - * - * The value is zero-based. When the result set is first returned the cursor - * will be at position -1, which is before the first row. - * After the last row is returned another call to next() will leave the cursor past - * the last entry, at a position of count(). - * - * @return Returns the current cursor position. - */ - virtual int GetRowIndex(int &position) const = 0; - - /** - * @brief Move the cursor a relative amount from current position. Positive offset move forward, - * negative offset move backward. - * - * @param offset Indicates the offset to be applied from the current position. - * @return Returns whether the requested move succeeded. - */ - virtual int GoTo(int offset) = 0; - - /** - * @brief Move the cursor to an absolute position. - * - * @param position Indicates the zero-based position to move to. - * @return Returns whether the requested move succeeded. - */ - virtual int GoToRow(int position) = 0; - - /** - * @brief Move the cursor to the first row. - * - * @return Returns whether the requested move succeeded. - */ - virtual int GoToFirstRow() = 0; - - /** - * @brief Move the cursor to the last row. - * - * @return Returns whether the requested move succeeded. - */ - virtual int GoToLastRow() = 0; - - /** - * @brief Move the cursor to the next row. - * - * @return Returns whether the requested move succeeded. - */ - virtual int GoToNextRow() = 0; - - /** - * @brief Move the cursor to the previous row. - * - * @return Returns whether the requested move succeeded. - */ - virtual int GoToPreviousRow() = 0; - - /** - * @brief Obtains whether the cursor is pointing to the position after the last row. - * - * @return Returns whether the cursor is after the last row. - */ - virtual int IsEnded(bool &result) = 0; - - /** - * @brief Obtains whether the cursor is pointing to the position before the first row. - * - * @return Returns whether the cursor is before the first row. - */ - virtual int IsStarted(bool &result) const = 0; - - /** - * @brief Obtains whether the cursor is pointing to the first row. - * - * @return Returns whether the cursor is pointing at the first entry. - */ - virtual int IsAtFirstRow(bool &result) const = 0; - - /** - * @brief Obtains whether the cursor is pointing to the last row. - * - * @return Returns whether the cursor is pointing at the last entry. - */ - virtual int IsAtLastRow(bool &result) = 0; - - /** - * @brief Obtains the value of the requested column as a byte array. - * - * @param columnIndex Indicates the zero-based index of the target column. - * @return Returns the value of the requested column as a byte array. - */ - virtual int GetBlob(int columnIndex, std::vector &blob) = 0; - - /** - * @brief Obtains the value of the requested column as a String. - * - * @param columnIndex Indicates the zero-based index of the target column. - * @return Returns the value of the requested column as a String. - */ - virtual int GetString(int columnIndex, std::string &value) = 0; - - /** - * @brief Obtains the value of the requested column as a int. - * - * @param columnIndex Indicates the zero-based index of the target column. - * @return Returns the value of the requested column as a int. - */ - virtual int GetInt(int columnIndex, int &value) = 0; - - /** - * @brief Obtains the value of the requested column as a long. - * - * @param columnIndex Indicates the zero-based index of the target column. - * @return Returns the value of the requested column as a long. - */ - virtual int GetLong(int columnIndex, int64_t &value) = 0; - - /** - * @brief Obtains the value of the requested column as a double. - * - * @param columnIndex Indicates the zero-based index of the target column. - * @return Returns the value of the requested column as a double. - */ - virtual int GetDouble(int columnIndex, double &value) = 0; - - /** - * @brief Obtains Whether the value of the requested column is null. - * - * @param columnIndex Indicates the zero-based index of the target column. - * @return Returns whether the column value is null. - */ - virtual int IsColumnNull(int columnIndex, bool &isNull) = 0; - - /** - * @brief Obtains Return true if the result set is closed. - * - * @return Returns true if the result set is closed. - */ - virtual bool IsClosed() const = 0; - - /** - * @brief Closes the result set, releasing all of its resources and making it completely invalid. + * @brief Gets the entire row of data for the current row from the result set. */ - virtual int Close() = 0; + RDB_API_EXPORT virtual int GetRow(RowEntity &rowEntity) = 0; }; } // namespace NativeRdb diff --git a/relational_store/interfaces/inner_api/rdb/mock/include/abs_result_set.h b/relational_store/interfaces/inner_api/rdb/mock/include/abs_result_set.h new file mode 100644 index 00000000..5bb0b3e2 --- /dev/null +++ b/relational_store/interfaces/inner_api/rdb/mock/include/abs_result_set.h @@ -0,0 +1,77 @@ +/* + * 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 +#include +#include +#include + +#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 &columnNames) override; + int GetBlob(int columnIndex, std::vector &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 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: + std::map columnMap_; + int columnCount_ = -1; + // The default position of the result set + static const int INIT_POS = -1; + /* + * 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_; + + // Indicates whether the result set is closed + bool isClosed; +}; +} // namespace NativeRdb +} // namespace OHOS + +#endif \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/framework/include/store/asset.h b/relational_store/interfaces/inner_api/rdb/mock/include/result_set.h similarity index 45% rename from datamgr_service/services/distributeddataservice/framework/include/store/asset.h rename to relational_store/interfaces/inner_api/rdb/mock/include/result_set.h index 8bc758d9..824bab2d 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/store/asset.h +++ b/relational_store/interfaces/inner_api/rdb/mock/include/result_set.h @@ -13,15 +13,35 @@ * limitations under the License. */ -#ifndef OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_STORE_INNER_ASSET_H -#define OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_STORE_INNER_ASSET_H +#ifndef NATIVE_RDB_RESULT_SET_H +#define NATIVE_RDB_RESULT_SET_H + #include -namespace OHOS::DistributedData { -struct Asset { - uint32_t version; - std::string name; - std::string modifyTime; - std::string size; +#include +#include +#include "remote_result_set.h" +#include "value_object.h" + +namespace OHOS { +namespace NativeRdb { +struct RowEntity { +public: + void Put(const std::string &name, const ValueObject &value); + ValueObject Get(const std::string &name) const; + ValueObject Get(const int index) const; + void Get(std::map &outValues) const; + void Clear(); +private: + std::map values_; + std::vector indexs_; }; -} -#endif // OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_STORE_INNER_ASSET_H + +class ResultSet : public RemoteResultSet { +public: + virtual ~ResultSet() {} + virtual int GetRow(RowEntity &rowEntity) = 0; +}; + +} // namespace NativeRdb +} // namespace OHOS +#endif diff --git a/relational_store/interfaces/inner_api/rdb/mock/include/value_object.h b/relational_store/interfaces/inner_api/rdb/mock/include/value_object.h index 099f81b9..1733b2fe 100644 --- a/relational_store/interfaces/inner_api/rdb/mock/include/value_object.h +++ b/relational_store/interfaces/inner_api/rdb/mock/include/value_object.h @@ -38,12 +38,13 @@ public: ValueObject(Type valueObject) noexcept; ValueObject(ValueObject &&valueObject) noexcept; ValueObject(const ValueObject &valueObject); - explicit ValueObject(int val); - explicit ValueObject(int64_t val); - explicit ValueObject(double val); - explicit ValueObject(bool val); - explicit ValueObject(const std::string &val); - explicit ValueObject(const std::vector &blob); + ValueObject(int val); + ValueObject(int64_t val); + ValueObject(double val); + ValueObject(bool val); + ValueObject(const std::string &val); + ValueObject(const char *val); + ValueObject(const std::vector &blob); ValueObject &operator=(ValueObject &&valueObject) noexcept; ValueObject &operator=(const ValueObject &valueObject); diff --git a/relational_store/test/js/rdb/BUILD.gn b/relational_store/test/js/rdb/BUILD.gn index 0d590223..a3b5ca97 100644 --- a/relational_store/test/js/rdb/BUILD.gn +++ b/relational_store/test/js/rdb/BUILD.gn @@ -20,4 +20,11 @@ group("unittest") { deps += [ "unittest/src:unittest" ] } + +group("performancetest") { + testonly = true + deps = [] + + deps += [ "performance/src:RdbPerfJsTest" ] +} ############################################################################### diff --git a/relational_store/test/js/rdb/performance/config.json b/relational_store/test/js/rdb/performance/config.json new file mode 100644 index 00000000..e1b1bc28 --- /dev/null +++ b/relational_store/test/js/rdb/performance/config.json @@ -0,0 +1,62 @@ +{ + "app": { + "bundleName": "com.example.myapplication", + "vendor": "example", + "version": { + "code": 1, + "name": "1.0" + }, + "apiVersion": { + "compatible": 4, + "target": 5 + } + }, + "deviceConfig": {}, + "module": { + "package": "com.example.myapplication", + "name": ".MyApplication", + "deviceType": [ + "tablet", + "default", + "phone" + ], + "distro": { + "deliveryWithInstall": true, + "moduleName": "entry", + "moduleType": "entry" + }, + "abilities": [ + { + "visible": true, + "skills": [ + { + "entities": [ + "entity.system.home" + ], + "actions": [ + "action.system.home" + ] + } + ], + "name": "com.example.myapplication.MainAbility", + "icon": "$media:icon", + "description": "$string:mainability_description", + "label": "MyApplication", + "type": "page", + "launchType": "standard" + } + ], + "js": [ + { + "pages": [ + "pages/index/index" + ], + "name": "default", + "window": { + "designWidth": 720, + "autoDesignWidth": false + } + } + ] + } +} diff --git a/relational_store/test/js/rdb/performance/openharmony_sx.p7b b/relational_store/test/js/rdb/performance/openharmony_sx.p7b new file mode 100644 index 0000000000000000000000000000000000000000..9be1e98fa4c0c28ca997ed660112fa16b194f0f5 GIT binary patch literal 3437 zcmcgvX>b$g8MY4FF(5FQyMT=#m||qU)nQ9cId-MBB-<-lvSdq&snM}IENNF>t+bK| zgowuF2vC|SxSZxNN5eHhV%(WPpbeB9Fc3;JDMtzMBv1-XAc2N~c2_tCXW&OCGw6qQ z-s9VS-tT?h=bI0tMS+~WDXqHJyCPmLzdbE-fV8Nd&*MRZfG8(#POFZG3xs@Lb{0ry z=R8j3wWo!5g=yjKx#BoZMFS)uA)H}cTp@-^K`9VV?RC3J59@}eik*>n|pRKOLZ zxdn7G!Yv@9O#y<&eUy{)vMXb;fQR)ffVAADQsEMXm;IBMDLfLD0w^U;6%HVo-0Q_5 zCHEa?DBuauNpZzoF+tK27w#n~?u%toS-DhR4k@Q*{7x^8Q=D6&kd^_~J#VVG2LXkL zaAy=}U*?Jto)9hx5MGjdp9hcQAu@tfk_;l!PeyxPY<8b&+&D!CyaBh9=8BSVKLpk4 z4Ml3yY|&Th)vyK4cpC{!uU8v2YBlVV`d~(nz&<@{G1oe*DHub1z7~J5*;s2bX<)_* zV_GbsPQg`(&rpxRb_*Od7}++3+liSw-$!1 zs5*g}EHWhI3i|!-FcfzYL0`SL-rq>LENC;PMl)G(0(1U2%Va|smp0UFx0xd@soZA* zD5LYc4OlbE7@ARt#h}rr3>K@bf%B#^-c+xz8Hr)0D5ExIFltezN@Hn8>o5d~bSfYtkc+_Z&kI#-N5_GhCg*V-^TSO=!G~ z(fXy{n2XV+k}6w_W`dTOP2a4u0ly;ANZ>4OxSKAzFB!yBzdo`gX zO?o|H@WiAw$y6l?=^3jA_Hy0S)nTYs12;4hKE&ekQ|>?|ZLJ}#F`2BczC7kdE4@xV zZBD_)Otwjhz+NSaz?d45!;FsGSu-#qh#hStD%B}f!mCT!KqzSo>I`NGH_9Dea$1Qi zg29Ydt!~lQVR99_T7#Hije~(12drl-P)SV?QR*9sus`8th-8^OQ7@xI$(Yp|^;bL1 zR50O$mDXw6P>i7B(TJ)ciPzTE>XY%X6HAa)b#OBRXv&~%Bw|J#Y><i4=e%95bjtw|cJp=#P#Pf#*luqI_wR;fISDCJhAqSG6R%xItn%~QtZ@m%&u zjGGLX;t6Ls62eQvNmf@v+}J%54^CygxRZ`?8X#r|wkev7(s;Ou4T#y1XNNf)h;o7z z8a^Lfq<1uH`E{G9E z*(=)Css_LSk=>E9jr)s5^2-!+MN=Ds}>1hRma4`uCIz9%p3O77839E{xf z4c_I?**|1`K2tg4!Hvyrou4BsJQuv*UfF)<%CelYIS>D^o?X)3+MK%la6kooW8&G@BU)Y0hT`+mOm$Z_%rB=a%o>I z!2c6lHyKQN)VjiFwa!eE^p8jc$sy$vB+8i25lI~6KPFFh$!o$avA~rj#L6xvR|Z83 z*WD6T9e+5Pyy=F+)pNTf{ny3cy>7Rkd3o*TS?TZJ`NS^NF2%HMkyS{?uJ$`!P4_L^ z1`NFDUbNyg_qREifgktnp1_v{Jbb`7m}2PTyUdOmtJj~m z9bB=ecw4_^rw1IW=of+>nrW5=d3k`3qHCxsIN_F{T1A545};;+fsyC&qChi+YV zr~M63H8ZLCPYmsjY>ls9cL%I)F|JIW-#+48$+lD4k*(P*kDM%zx_fvu4u5ZYUnI}5 zdrycFq>xFU)&X3p@pP2u%$o}}YcRn(MhJ&B2o?KS@cIVz>Ye%o^xV?CB{_Qhu z;}_q1bvO^g{8<3!gYbo4Di{8qzV+(9 zdlmksohQmRTs@qB;(Wo?dER_ux6XQb@q$tQPW?CMu6GVQd;R=iR;-S{Kr%Zks7>b1 zNs{|-+jhObYE}NR&`TGGr^h^4bjh%c>R#@=8nM&Md>_a+zVulsl;){flFekV1t9ob z+SqfV_Pv3$2f)bQ8%Ul2>fdYR^1zs0BQF~olsOj5AodC&Q_7SMFzsz2 z9newxE&jodk~tNHwl%LBMMDbrk=(^b literal 0 HcmV?d00001 diff --git a/relational_store/test/js/rdb/performance/src/BUILD.gn b/relational_store/test/js/rdb/performance/src/BUILD.gn new file mode 100644 index 00000000..e7b7cdd2 --- /dev/null +++ b/relational_store/test/js/rdb/performance/src/BUILD.gn @@ -0,0 +1,24 @@ +# 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. + +import("//build/test.gni") + +module_output_path = "relational_store/performance" + +ohos_js_unittest("RdbPerfJsTest") { + module_out_path = module_output_path + + hap_profile = "../config.json" + + certificate_profile = "../openharmony_sx.p7b" +} diff --git a/relational_store/test/js/rdb/performance/src/PredicatestPerf.js b/relational_store/test/js/rdb/performance/src/PredicatestPerf.js new file mode 100644 index 00000000..30057c99 --- /dev/null +++ b/relational_store/test/js/rdb/performance/src/PredicatestPerf.js @@ -0,0 +1,506 @@ +/* + * 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. + */ + +import {describe, beforeAll, beforeEach, afterEach, afterAll, it, expect, Assert} from 'deccjsunit/index'; +import dataRdb from '@ohos.data.rdb'; +import deviceInfo from '@ohos.deviceInfo'; + +const TAG = "[RDB_PREDICATES_PERF]"; + +const BASE_COUNT = 2000; // loop times +const BASE_COUNT_FIRST = 200; +const BASE_COUNT_SECOND = 10; +const BASE_LINE_TABLE = 500; // callback tablet base line +const BASE_LINE_PHONE = 1000; // callback phone base line +const BASE_LINE = (deviceInfo.deviceType == "tablet") ? BASE_LINE_TABLE : BASE_LINE_PHONE; + +describe('predicatesPerf', function () { + beforeAll(async function () { + console.info(TAG + 'beforeAll'); + }) + beforeEach(async function () { + console.info(TAG + 'beforeEach'); + }) + afterEach(async function () { + console.info(TAG + 'afterEach'); + }) + afterAll(async function () { + console.info(TAG + 'afterAll'); + }) + + console.log(TAG + "*************Unit Test Begin*************"); + + it('SUB_DDM_PERF_RDB_Predicates_inDevices_001', 0, async function (done) { + let startTime = new Date().getTime(); + for (let i = 0; i < BASE_COUNT_FIRST; i++) { + let predicates = new dataRdb.RdbPredicates("test"); + for (let j = 0; j < BASE_COUNT_SECOND; j++) { + predicates.inDevices(['123']); + } + } + let endTime = new Date().getTime(); + let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; + console.info(TAG + " the Predicates_inDevices average time is: " + averageTime + " μs"); + expect(averageTime < BASE_LINE).assertTrue(); + done(); + }) + + it('SUB_DDM_PERF_RDB_Predicates_inAllDevices_001', 0, async function (done) { + let startTime = new Date().getTime(); + for (let i = 0; i < BASE_COUNT_FIRST; i++) { + let predicates = new dataRdb.RdbPredicates("test"); + for (let j = 0; j < BASE_COUNT_SECOND; j++) { + predicates.inAllDevices(); + } + } + let endTime = new Date().getTime(); + let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; + console.info(TAG + " the Predicates_inAllDevices average time is: " + averageTime + " μs"); + expect(averageTime < BASE_LINE).assertTrue(); + done(); + }) + + it('SUB_DDM_PERF_RDB_Predicates_equalTo_001', 0, async function (done) { + let startTime = new Date().getTime(); + for (let i = 0; i < BASE_COUNT_FIRST; i++) { + let predicates = new dataRdb.RdbPredicates("test"); + for (let j = 0; j < BASE_COUNT_SECOND; j++) { + predicates.equalTo("name", "lisi"); + } + } + let endTime = new Date().getTime(); + let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; + console.info(TAG + " the Predicates_equalTo average time is: " + averageTime + " μs"); + expect(averageTime < BASE_LINE).assertTrue(); + done(); + }) + + it('SUB_DDM_PERF_RDB_Predicates_notEqualTo_001', 0, async function (done) { + let startTime = new Date().getTime(); + for (let i = 0; i < BASE_COUNT_FIRST; i++) { + let predicates = new dataRdb.RdbPredicates("test"); + for (let j = 0; j < BASE_COUNT_SECOND; j++) { + predicates.notEqualTo("name", "lisi"); + } + } + let endTime = new Date().getTime(); + let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; + console.info(TAG + " the Predicates_notEqualTo average time is: " + averageTime + " μs"); + expect(averageTime < BASE_LINE).assertTrue(); + done(); + }) + + it('SUB_DDM_PERF_RDB_Predicates_beginWrap_001', 0, async function (done) { + let startTime = new Date().getTime(); + for (let i = 0; i < BASE_COUNT_FIRST; i++) { + let predicates = new dataRdb.RdbPredicates("test"); + for (let j = 0; j < BASE_COUNT_SECOND; j++) { + predicates.beginWrap(); + } + } + let endTime = new Date().getTime(); + let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; + console.info(TAG + " the Predicates_beginWrap average time is: " + averageTime + " μs"); + expect(averageTime < BASE_LINE).assertTrue(); + done(); + }) + + it('SUB_DDM_PERF_RDB_Predicates_endWrap_001', 0, async function (done) { + let startTime = new Date().getTime(); + for (let i = 0; i < BASE_COUNT_FIRST; i++) { + let predicates = new dataRdb.RdbPredicates("test"); + for (let j = 0; j < BASE_COUNT_SECOND; j++) { + predicates.equalTo("name", "lisi"); + predicates.endWrap(); + } + } + let endTime = new Date().getTime(); + let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; + console.info(TAG + " the Predicates_endWrap average time is: " + averageTime + " μs"); + expect(averageTime < BASE_LINE).assertTrue(); + done(); + }) + + it('SUB_DDM_PERF_RDB_Predicates_or_001', 0, async function (done) { + let startTime = new Date().getTime(); + for (let i = 0; i < BASE_COUNT_FIRST; i++) { + let predicates = new dataRdb.RdbPredicates("test"); + for (let j = 0; j < BASE_COUNT_SECOND; j++) { + predicates.equalTo("name", "lisi"); + predicates.or(); + predicates.equalTo("age", 18); + } + } + let endTime = new Date().getTime(); + let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; + console.info(TAG + " the Predicates_or average time is: " + averageTime + " μs"); + expect(averageTime < BASE_LINE).assertTrue(); + done(); + }) + + it('SUB_DDM_PERF_RDB_Predicates_and_001', 1, async function (done) { + let startTime = new Date().getTime(); + for (let i = 0; i < BASE_COUNT_FIRST; i++) { + let predicates = new dataRdb.RdbPredicates("test"); + for (let j = 0; j < BASE_COUNT_SECOND; j++) { + predicates.equalTo("name", "lisi"); + predicates.and(); + predicates.equalTo("name", "zs"); + } + } + let endTime = new Date().getTime(); + let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; + console.info(TAG + " the Predicates_and average time is: " + averageTime + " μs"); + expect(averageTime < BASE_LINE).assertTrue(); + done(); + }) + + it('SUB_DDM_PERF_RDB_Predicates_contains_001', 0, async function (done) { + let startTime = new Date().getTime(); + for (let i = 0; i < BASE_COUNT_FIRST; i++) { + let predicates = new dataRdb.RdbPredicates("test"); + for (let j = 0; j < BASE_COUNT_SECOND; j++) { + predicates.contains("name", "lisi"); + } + } + let endTime = new Date().getTime(); + let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; + console.info(TAG + " the Predicates_contains average time is: " + averageTime + " μs"); + expect(averageTime < BASE_LINE).assertTrue(); + done(); + }) + + it('SUB_DDM_PERF_RDB_Predicates_beginsWith_001', 0, async function (done) { + let startTime = new Date().getTime(); + for (let i = 0; i < BASE_COUNT_FIRST; i++) { + let predicates = new dataRdb.RdbPredicates("test"); + for (let j = 0; j < BASE_COUNT_SECOND; j++) { + predicates.beginsWith("name", "lisi"); + } + } + let endTime = new Date().getTime(); + let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; + console.info(TAG + " the Predicates_beginsWith average time is: " + averageTime + " μs"); + expect(averageTime < BASE_LINE).assertTrue(); + done(); + }) + + it('SUB_DDM_PERF_RDB_Predicates_endWith_001', 0, async function (done) { + let startTime = new Date().getTime(); + for (let i = 0; i < BASE_COUNT_FIRST; i++) { + let predicates = new dataRdb.RdbPredicates("test"); + for (let j = 0; j < BASE_COUNT_SECOND; j++) { + predicates.endsWith("name", "lisi"); + } + } + let endTime = new Date().getTime(); + let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; + console.info(TAG + " the Predicates_endWith average time is: " + averageTime + " μs"); + expect(averageTime < BASE_LINE).assertTrue(); + done(); + }) + + it('SUB_DDM_PERF_RDB_Predicates_isNull_001', 0, async function (done) { + let startTime = new Date().getTime(); + for (let i = 0; i < BASE_COUNT_FIRST; i++) { + let predicates = new dataRdb.RdbPredicates("test"); + for (let j = 0; j < BASE_COUNT_SECOND; j++) { + predicates.isNull("name"); + } + } + let endTime = new Date().getTime(); + let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; + console.info(TAG + " the Predicates_isNull average time is: " + averageTime + " μs"); + expect(averageTime < BASE_LINE).assertTrue(); + done(); + }) + + it('SUB_DDM_PERF_RDB_Predicates_isNotNull_001', 0, async function (done) { + let startTime = new Date().getTime(); + for (let i = 0; i < BASE_COUNT_FIRST; i++) { + let predicates = new dataRdb.RdbPredicates("test"); + for (let j = 0; j < BASE_COUNT_SECOND; j++) { + predicates.isNotNull("name"); + } + } + let endTime = new Date().getTime(); + let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; + console.info(TAG + " the Predicates_isNotNull average time is: " + averageTime + " μs"); + expect(averageTime < BASE_LINE).assertTrue(); + done(); + }) + + it('SUB_DDM_PERF_RDB_Predicates_like_001', 0, async function (done) { + let startTime = new Date().getTime(); + for (let i = 0; i < BASE_COUNT_FIRST; i++) { + let predicates = new dataRdb.RdbPredicates("test"); + for (let j = 0; j < BASE_COUNT_SECOND; j++) { + predicates.like("name", "li"); + } + } + let endTime = new Date().getTime(); + let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; + console.info(TAG + " the Predicates_like average time is: " + averageTime + " μs"); + expect(averageTime < BASE_LINE).assertTrue(); + done(); + }) + + it('SUB_DDM_PERF_RDB_Predicates_glob_001', 0, async function (done) { + let startTime = new Date().getTime(); + for (let i = 0; i < BASE_COUNT_FIRST; i++) { + let predicates = new dataRdb.RdbPredicates("test"); + for (let j = 0; j < BASE_COUNT_SECOND; j++) { + predicates.glob("name", "li"); + } + } + let endTime = new Date().getTime(); + let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; + console.info(TAG + " the Predicates_glob average time is: " + averageTime + " μs"); + expect(averageTime < BASE_LINE).assertTrue(); + done(); + }) + + it('SUB_DDM_PERF_RDB_Predicates_between_001', 0, async function (done) { + let startTime = new Date().getTime(); + for (let i = 0; i < BASE_COUNT_FIRST; i++) { + let predicates = new dataRdb.RdbPredicates("test"); + for (let j = 0; j < BASE_COUNT_SECOND; j++) { + predicates.between("age", 1, 100); + } + } + let endTime = new Date().getTime(); + let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; + console.info(TAG + " the Predicates_between average time is: " + averageTime + " μs"); + expect(averageTime < BASE_LINE).assertTrue(); + done(); + }) + + it('SUB_DDM_PERF_RDB_Predicates_notBetween_001', 0, async function (done) { + let startTime = new Date().getTime(); + for (let i = 0; i < BASE_COUNT_FIRST; i++) { + let predicates = new dataRdb.RdbPredicates("test"); + for (let j = 0; j < BASE_COUNT_SECOND; j++) { + predicates.notBetween("age", 1, 100); + } + } + let endTime = new Date().getTime(); + let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; + console.info(TAG + " the Predicates_notBetween average time is: " + averageTime + " μs"); + expect(averageTime < BASE_LINE).assertTrue(); + done(); + }) + + it('SUB_DDM_PERF_RDB_Predicates_greaterThan_001', 0, async function (done) { + let startTime = new Date().getTime(); + for (let i = 0; i < BASE_COUNT_FIRST; i++) { + let predicates = new dataRdb.RdbPredicates("test"); + for (let j = 0; j < BASE_COUNT_SECOND; j++) { + predicates.greaterThan("age", 1); + } + } + let endTime = new Date().getTime(); + let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; + console.info(TAG + " the Predicates_greaterThan average time is: " + averageTime + " μs"); + expect(averageTime < BASE_LINE).assertTrue(); + done(); + }) + + it('SUB_DDM_PERF_RDB_Predicates_lessThan_001', 0, async function (done) { + let startTime = new Date().getTime(); + for (let i = 0; i < BASE_COUNT_FIRST; i++) { + let predicates = new dataRdb.RdbPredicates("test"); + for (let j = 0; j < BASE_COUNT_SECOND; j++) { + predicates.lessThan("age", 1000); + } + } + let endTime = new Date().getTime(); + let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; + console.info(TAG + " the Predicates_lessThan average time is: " + averageTime + " μs"); + expect(averageTime < BASE_LINE).assertTrue(); + done(); + }) + + it('SUB_DDM_PERF_RDB_Predicates_greaterThanOrEqualTo_001', 0, async function (done) { + let startTime = new Date().getTime(); + for (let i = 0; i < BASE_COUNT_FIRST; i++) { + let predicates = new dataRdb.RdbPredicates("test"); + for (let j = 0; j < BASE_COUNT_SECOND; j++) { + predicates.greaterThanOrEqualTo("age", 1000); + } + } + let endTime = new Date().getTime(); + let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; + console.info(TAG + " the Predicates_greaterThanOrEqualTo average time is: " + averageTime + " μs"); + expect(averageTime < BASE_LINE).assertTrue(); + done(); + }) + + it('SUB_DDM_PERF_RDB_Predicates_lessThanOrEqualTo_001', 0, async function (done) { + let startTime = new Date().getTime(); + for (let i = 0; i < BASE_COUNT_FIRST; i++) { + let predicates = new dataRdb.RdbPredicates("test"); + for (let j = 0; j < BASE_COUNT_SECOND; j++) { + predicates.lessThanOrEqualTo("age", 1000); + } + } + let endTime = new Date().getTime(); + let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; + console.info(TAG + " the Predicates_lessThanOrEqualTo average time is: " + averageTime + " μs"); + expect(averageTime < BASE_LINE).assertTrue(); + done(); + }) + + it('SUB_DDM_PERF_RDB_Predicates_orderByAsc_001', 0, async function (done) { + let startTime = new Date().getTime(); + for (let i = 0; i < BASE_COUNT_FIRST; i++) { + let predicates = new dataRdb.RdbPredicates("test"); + for (let j = 0; j < BASE_COUNT_SECOND; j++) { + predicates.orderByAsc("name"); + } + } + let endTime = new Date().getTime(); + let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; + console.info(TAG + " the Predicates_orderByAsc average time is: " + averageTime + " μs"); + expect(averageTime < BASE_LINE).assertTrue(); + done(); + }) + + it('SUB_DDM_PERF_RDB_Predicates_orderByDesc_001', 0, async function (done) { + let startTime = new Date().getTime(); + for (let i = 0; i < BASE_COUNT_FIRST; i++) { + let predicates = new dataRdb.RdbPredicates("test"); + for (let j = 0; j < BASE_COUNT_SECOND; j++) { + predicates.orderByDesc("name"); + } + } + let endTime = new Date().getTime(); + let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; + console.info(TAG + " the Predicates_orderByDesc average time is: " + averageTime + " μs"); + expect(averageTime < BASE_LINE).assertTrue(); + done(); + }) + + it('SUB_DDM_PERF_RDB_Predicates_distinct_001', 0, async function (done) { + let startTime = new Date().getTime(); + for (let i = 0; i < BASE_COUNT_FIRST; i++) { + let predicates = new dataRdb.RdbPredicates("test"); + for (let j = 0; j < BASE_COUNT_SECOND; j++) { + predicates.distinct(); + } + } + let endTime = new Date().getTime(); + let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; + console.info(TAG + " the Predicates_distinct average time is: " + averageTime + " μs"); + expect(averageTime < BASE_LINE).assertTrue(); + done(); + }) + + it('SUB_DDM_PERF_RDB_Predicates_limitAs_001', 0, async function (done) { + let startTime = new Date().getTime(); + for (let i = 0; i < BASE_COUNT; i++) { + let predicates = new dataRdb.RdbPredicates("test"); + predicates.limitAs(6); + } + let endTime = new Date().getTime(); + let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; + console.info(TAG + " the Predicates_limitAs average time is: " + averageTime + " μs"); + expect(averageTime < BASE_LINE).assertTrue(); + done(); + }) + + it('SUB_DDM_PERF_RDB_Predicates_offsetAs_001', 0, async function (done) { + let startTime = new Date().getTime(); + for (let i = 0; i < BASE_COUNT; i++) { + let predicates = new dataRdb.RdbPredicates("test"); + predicates.offsetAs(6); + } + let endTime = new Date().getTime(); + let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; + console.info(TAG + " the Predicates_offsetAs average time is: " + averageTime + " μs"); + expect(averageTime < BASE_LINE).assertTrue(); + done(); + }) + + it('SUB_DDM_PERF_RDB_Predicates_groupBy_001', 0, async function (done) { + let nameArr = new Array(); + nameArr.push("id"); + nameArr.push("name"); + let startTime = new Date().getTime(); + for (let i = 0; i < BASE_COUNT_FIRST; i++) { + let predicates = new dataRdb.RdbPredicates("test"); + for (let j = 0; j < BASE_COUNT_SECOND; j++) { + predicates.groupBy(nameArr); + } + } + let endTime = new Date().getTime(); + let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; + console.info(TAG + " the Predicates_groupBy average time is: " + averageTime + " μs"); + expect(averageTime < BASE_LINE).assertTrue(); + done(); + }) + + it('SUB_DDM_PERF_RDB_Predicates_indexedBy_001', 0, async function (done) { + let startTime = new Date().getTime(); + for (let i = 0; i < BASE_COUNT_FIRST; i++) { + let predicates = new dataRdb.RdbPredicates("test"); + for (let j = 0; j < BASE_COUNT_SECOND; j++) { + predicates.indexedBy("name"); + } + } + let endTime = new Date().getTime(); + let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; + console.info(TAG + " the Predicates_indexedBy average time is: " + averageTime + " μs"); + expect(averageTime < BASE_LINE).assertTrue(); + done(); + }) + + it('SUB_DDM_PERF_RDB_Predicates_in_001', 0, async function (done) { + let nameArr = new Array(); + nameArr.push("id"); + nameArr.push("name"); + let startTime = new Date().getTime(); + for (let i = 0; i < BASE_COUNT_FIRST; i++) { + let predicates = new dataRdb.RdbPredicates("test"); + for (let j = 0; j < BASE_COUNT_SECOND; j++) { + predicates.in("name", nameArr); + } + } + let endTime = new Date().getTime(); + let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; + console.info(TAG + " the Predicates_in average time is: " + averageTime + " μs"); + expect(averageTime < BASE_LINE).assertTrue(); + done(); + }) + + it('SUB_DDM_PERF_RDB_Predicates_notIn(_001', 0, async function (done) { + let nameArr = new Array(); + nameArr.push("zhangsan"); + nameArr.push("lisi"); + let startTime = new Date().getTime(); + for (let i = 0; i < BASE_COUNT_FIRST; i++) { + let predicates = new dataRdb.RdbPredicates("test"); + for (let j = 0; j < BASE_COUNT_SECOND; j++) { + predicates.notIn("name", nameArr); + } + } + let endTime = new Date().getTime(); + let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; + console.info(TAG + " the Predicates_notIn average time is: " + averageTime + " μs"); + expect(averageTime < BASE_LINE).assertTrue(); + done(); + }) + + console.info(TAG + "*************Unit Test End*************") +}) \ No newline at end of file diff --git a/relational_store/test/js/rdb/performance/src/RdbHelperCallbackPerf.js b/relational_store/test/js/rdb/performance/src/RdbHelperCallbackPerf.js new file mode 100644 index 00000000..14d02c2a --- /dev/null +++ b/relational_store/test/js/rdb/performance/src/RdbHelperCallbackPerf.js @@ -0,0 +1,93 @@ +/* + * 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. + */ + +import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect, Assert } from 'deccjsunit/index'; +import dataRdb from '@ohos.data.rdb'; +import featureAbility from '@ohos.ability.featureAbility'; +import deviceInfo from '@ohos.deviceInfo'; + +const TAG = "[RDBHELPER_CALLBACK]"; + +const DB_NAME = "rdbCallback.db"; +const STORE_CONFIG = { + name: DB_NAME, +} +let context = featureAbility.getContext(); +var rdbStore = undefined; +const BASE_COUNT = 2000; // loop times +const BASE_LINE_TABLE = 2500; // callback tablet base line +const BASE_LINE_PHONE = 3000; // callback phone base line +const BASE_LINE = (deviceInfo.deviceType == "tablet") ? BASE_LINE_TABLE : BASE_LINE_PHONE; + +describe('rdbHelperCallbackPerf', function () { + beforeAll(async function () { + console.info(TAG + 'beforeAll'); + }) + beforeEach(async function () { + console.info(TAG + 'beforeEach'); + }) + afterEach(async function () { + console.info(TAG + 'afterEach'); + }) + afterAll(async function () { + console.info(TAG + 'afterAll'); + rdbStore = null + await dataRdb.deleteRdbStore(context, DB_NAME); + }) + + console.log(TAG + "*************Unit Test Begin*************"); + + it('SUB_DDM_PERF_RDB_getRdbStore_Callback_001', 0, async function (done) { + let averageTime = 0; + + async function getRdbStoreCallBackPerf(index) { + dataRdb.getRdbStore(context, STORE_CONFIG, 1, function (err, rdbStore) { + if (index < BASE_COUNT) { + getRdbStoreCallBackPerf(index + 1); + } else { + let endTime = new Date().getTime(); + averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; + console.info(TAG + " the getRdbStore_Callback average time is: " + averageTime + " μs"); + expect(averageTime < BASE_LINE).assertTrue(); + done(); + } + }) + } + + let startTime = new Date().getTime(); + await getRdbStoreCallBackPerf(0); + }) + + it('SUB_DDM_PERF_RDB_deleteRdbStore_Callback_001', 0, async function (done) { + let averageTime = 0; + + async function deleteRdbStoreCallBackPerf(index) { + dataRdb.deleteRdbStore(context, DB_NAME, function (err, data) { + if (index < BASE_COUNT) { + deleteRdbStoreCallBackPerf(index + 1); + } else { + let endTime = new Date().getTime(); + averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; + console.info(TAG + " the deleteRdbStore_Callback average time is: " + averageTime + " μs"); + expect(averageTime < BASE_LINE).assertTrue(); + done(); + } + }) + } + + let startTime = new Date().getTime(); + await deleteRdbStoreCallBackPerf(0); + }) +}) \ No newline at end of file diff --git a/relational_store/test/js/rdb/performance/src/RdbHelperPromisePerf.js b/relational_store/test/js/rdb/performance/src/RdbHelperPromisePerf.js new file mode 100644 index 00000000..330ffcd2 --- /dev/null +++ b/relational_store/test/js/rdb/performance/src/RdbHelperPromisePerf.js @@ -0,0 +1,78 @@ +/* + * 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. + */ + +import {describe, beforeAll, beforeEach, afterEach, afterAll, it, expect, Assert} from 'deccjsunit/index'; +import dataRdb from '@ohos.data.rdb'; +import featureAbility from '@ohos.ability.featureAbility'; +import deviceInfo from '@ohos.deviceInfo'; + +const TAG = "[RDBHELPER_PROMISE]"; + +const DB_NAME = "rdbPromise.db"; +const STORE_CONFIG = { + name: DB_NAME, +} +let context = featureAbility.getContext(); +var rdbStore = undefined; +const BASE_COUNT = 2000; // loop times +const BASE_LINE_TABLE = 2500; // callback tablet base line +const BASE_LINE_PHONE = 3000; // callback phone base line +const BASE_LINE = (deviceInfo.deviceType == "tablet") ? BASE_LINE_TABLE : BASE_LINE_PHONE; + +describe('rdbHelperPromisePerf', function () { + beforeAll(async function () { + console.info(TAG + 'beforeAll'); + }) + beforeEach(async function () { + console.info(TAG + 'beforeEach'); + }) + afterEach(async function () { + console.info(TAG + 'afterEach'); + }) + afterAll(async function () { + console.info(TAG + 'afterAll'); + rdbStore = null; + await dataRdb.deleteRdbStore(context, DB_NAME); + }) + + console.log(TAG + "*************Unit Test Begin*************"); + + it('SUB_DDM_PERF_RDB_getRdbStore_Promise_001', 0, async function (done) { + let averageTime = 0; + let startTime = new Date().getTime(); + for (var i = 0; i < BASE_COUNT; i++) { + await dataRdb.getRdbStore(context, STORE_CONFIG, 1); + } + let endTime = new Date().getTime(); + averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; + console.info(TAG + " the getRdbStore_Promise average time is: " + averageTime + " μs"); + expect(averageTime < BASE_LINE).assertTrue(); + done(); + }) + + it('SUB_DDM_PERF_RDB_deleteRdbStore_Promise_001', 0, async function (done) { + let averageTime = 0; + let startTime = new Date().getTime(); + for (var i = 0; i < BASE_COUNT; i++) { + await dataRdb.deleteRdbStore(context, DB_NAME, 1); + } + let endTime = new Date().getTime(); + averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; + console.info(TAG + " the deleteRdbStore_Promise average time is: " + averageTime + " μs"); + expect(averageTime < BASE_LINE).assertTrue(); + done(); + console.info(TAG + "*************Unit Test End*************") + }) +}) \ No newline at end of file diff --git a/relational_store/test/js/rdb/performance/src/RdbStoreCallbackPerf.js b/relational_store/test/js/rdb/performance/src/RdbStoreCallbackPerf.js new file mode 100644 index 00000000..52b39810 --- /dev/null +++ b/relational_store/test/js/rdb/performance/src/RdbStoreCallbackPerf.js @@ -0,0 +1,125 @@ +/* + * 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. + */ + +import {describe, beforeAll, beforeEach, afterEach, afterAll, it, expect, Assert} from 'deccjsunit/index'; +import dataRdb from '@ohos.data.rdb'; +import featureAbility from '@ohos.ability.featureAbility'; +import deviceInfo from '@ohos.deviceInfo'; + +const TAG = "[RDBSTORE_CALLBACK]"; +const CREATE_TABLE_TEST = "CREATE TABLE IF NOT EXISTS test (id INTEGER PRIMARY KEY AUTOINCREMENT, " + + "name TEXT, age INTEGER, salary REAL, blobType BLOB)"; + +const DB_NAME = "rdbStoreCallback.db"; +const STORE_CONFIG = { + name: DB_NAME, +} +let context = featureAbility.getContext(); +var rdbStore = undefined; +const BASE_COUNT = 1000; // loop times +const INSERT_BASE_COUNT = 300; +const BASE_LINE_TABLE = 1800; // callback tablet base line +const BASE_LINE_PHONE = 7000; // callback phone base line +const BASE_LINE = (deviceInfo.deviceType == "tablet") ? BASE_LINE_TABLE : BASE_LINE_PHONE; + +describe('rdbStoreCallbackPerf', function () { + beforeAll(async function () { + console.info(TAG + 'beforeAll'); + rdbStore = await dataRdb.getRdbStore(context, STORE_CONFIG, 1); + }) + beforeEach(async function () { + console.info(TAG + 'beforeEach'); + await rdbStore.executeSql(CREATE_TABLE_TEST, null); + await prepareTestData(); + }) + afterEach(async function () { + console.info(TAG + 'afterEach'); + await rdbStore.executeSql("drop table test"); + }) + afterAll(async function () { + console.info(TAG + 'afterAll'); + rdbStore = null; + await dataRdb.deleteRdbStore(context, DB_NAME); + }) + + async function prepareTestData() { + console.info(TAG + "prepare for query performance test"); + var u8 = new Uint8Array([1, 2, 3]); + var valueBucket = { + "name": "zhangsan", + "age": 18, + "salary": 100.5, + "blobType": u8, + } + await rdbStore.insert("test", valueBucket); + } + + console.log(TAG + "*************Unit Test Begin*************"); + + it('SUB_DDM_PERF_RDB_query_Callback_001', 0, async function (done) { + let averageTime = 0; + let predicates = new dataRdb.RdbPredicates("test"); + predicates.equalTo("age", 10); + + async function queryCallbackPerf(index) { + rdbStore.query(predicates, [], function (err, resultSet) { + resultSet.close(); + if (index < BASE_COUNT) { + queryCallbackPerf(index + 1); + } else { + let endTime = new Date().getTime(); + averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; + console.info(TAG + " the query_Callback average time is: " + averageTime + " μs"); + expect(averageTime < BASE_LINE).assertTrue(); + console.info(TAG + "*************Unit Test End*************"); + done(); + } + }) + } + + let startTime = new Date().getTime(); + queryCallbackPerf(0); + }) + + it('SUB_DDM_PERF_RDB_insert_Callback_001', 0, async function (done) { + let averageTime = 0; + var uBlob = new Uint8Array([1, 2, 3]); + var insertValueBucket = { + "name": "zhangsan", + "age": 18, + "salary": 100.5, + "blobType": uBlob, + } + let predicates = new dataRdb.RdbPredicates("test"); + predicates.equalTo("age", 10); + + async function InsertCallbackPerf(index) { + rdbStore.insert("test", insertValueBucket, function (err, data) { + if (index < INSERT_BASE_COUNT) { + InsertCallbackPerf(index + 1); + } else { + let endTime = new Date().getTime(); + averageTime = ((endTime - startTime) * 1000) / INSERT_BASE_COUNT; + console.info(TAG + " the insert_Callback average time is: " + averageTime + " μs"); + expect(averageTime < BASE_LINE).assertTrue(); + done(); + } + }) + } + + let startTime = new Date().getTime(); + InsertCallbackPerf(0); + }) +}) \ No newline at end of file diff --git a/relational_store/test/js/rdb/performance/src/RdbStoreOthersCallbackPerf.js b/relational_store/test/js/rdb/performance/src/RdbStoreOthersCallbackPerf.js new file mode 100644 index 00000000..03ced635 --- /dev/null +++ b/relational_store/test/js/rdb/performance/src/RdbStoreOthersCallbackPerf.js @@ -0,0 +1,165 @@ +/* + * 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. + */ + +import {describe, beforeAll, beforeEach, afterEach, afterAll, it, expect, Assert} from 'deccjsunit/index'; +import dataRdb from '@ohos.data.rdb'; +import featureAbility from '@ohos.ability.featureAbility'; +import deviceInfo from '@ohos.deviceInfo'; + +const TAG = "[RDBSTORE_OTHERS_CALLBACK]"; +const CREATE_TABLE_TEST = "CREATE TABLE IF NOT EXISTS test (id INTEGER PRIMARY KEY AUTOINCREMENT, " + + "name TEXT, age INTEGER, salary REAL, blobType BLOB)"; + +const DB_NAME = "rdbUpdateCallback.db"; +const STORE_CONFIG = { + name: DB_NAME, +} +let context = featureAbility.getContext(); +var rdbStore = undefined; +const BASE_COUNT = 1000; // loop times +const SPECIAL_BASE_COUNT = 300; +const BASE_LINE_TABLE = 1800; // callback tablet base line +const BASE_LINE_PHONE = 15000; // callback phone base line +const BASE_LINE = (deviceInfo.deviceType == "tablet") ? BASE_LINE_TABLE : BASE_LINE_PHONE; + +describe('rdbStoreOthersCallbackPerf', function () { + beforeAll(async function () { + console.info(TAG + 'beforeAll'); + rdbStore = await dataRdb.getRdbStore(context, STORE_CONFIG, 1); + }) + beforeEach(async function () { + console.info(TAG + 'beforeEach'); + await rdbStore.executeSql(CREATE_TABLE_TEST, null); + await prepareTestData(); + }) + afterEach(async function () { + console.info(TAG + 'afterEach'); + await rdbStore.executeSql("drop table test"); + }) + afterAll(async function () { + console.info(TAG + 'afterAll'); + rdbStore = null; + await dataRdb.deleteRdbStore(context, DB_NAME); + }) + + async function prepareTestData() { + console.info(TAG + "prepare for query performance test"); + var u8 = new Uint8Array([1, 2, 3]); + var valueBucket = { + "name": "zhangsan", + "age": 18, + "salary": 100.5, + "blobType": u8, + } + await rdbStore.insert("test", valueBucket); + } + + console.log(TAG + "*************Unit Test Begin*************"); + + it('SUB_DDM_PERF_RDB_update_Callback_001', 0, async function (done) { + let averageTime = 0; + var uBlob = new Uint8Array([1, 2, 3]) + var updateVB = { + "name": "zhangsan", + "age": 18, + "salary": 100.5, + "blobType": uBlob, + } + let predicates = new dataRdb.RdbPredicates("test"); + + async function updateCallbackPerf(index) { + predicates.equalTo("age", 18); + rdbStore.update(updateVB, predicates, function (err, data) { + if (index < SPECIAL_BASE_COUNT) { + updateCallbackPerf(index + 1); + } else { + let endTime = new Date().getTime(); + averageTime = ((endTime - startTime) * 1000) / SPECIAL_BASE_COUNT; + console.info(TAG + " the update_Callback average time is: " + averageTime + " μs"); + expect(averageTime < BASE_LINE).assertTrue(); + done(); + } + }) + } + + let startTime = new Date().getTime(); + updateCallbackPerf(0); + }) + + it('SUB_DDM_PERF_RDB_delete_Callback_001', 0, async function (done) { + let averageTime = 0; + let predicates = new dataRdb.RdbPredicates("test"); + predicates.equalTo("age", 0); + + async function deleteCallbackPerf(index) { + rdbStore.delete(predicates, function (err, data) { + if (index < BASE_COUNT) { + deleteCallbackPerf(index + 1) + } else { + let endTime = new Date().getTime(); + averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; + console.info(TAG + " the delete_Callback average time is: " + averageTime + " μs"); + expect(averageTime < BASE_LINE).assertTrue(); + done(); + } + }) + } + + let startTime = new Date().getTime(); + deleteCallbackPerf(0); + }) + + it('SUB_DDM_PERF_RDB_querySql_Callback_001', 0, async function (done) { + let averageTime = 0; + + async function querySqlCallbackPerf(index) { + rdbStore.querySql("select * from test", [], function (err, data) { + if (index < BASE_COUNT) { + querySqlCallbackPerf(index + 1); + } else { + let endTime = new Date().getTime(); + averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; + console.info(TAG + " the querySql_Callback average time is: " + averageTime + " μs"); + expect(averageTime < BASE_LINE).assertTrue(); + done(); + } + }) + } + + let startTime = new Date().getTime(); + querySqlCallbackPerf(0); + }) + + it('SUB_DDM_PERF_RDB_executeSql_Callback_001', 0, async function (done) { + let averageTime = 0; + + async function executeSqlCallbackPerf(index) { + rdbStore.executeSql("insert into test (name, age) values ('tom', 22)", function (err, data) { + if (index < SPECIAL_BASE_COUNT) { + executeSqlCallbackPerf(index + 1); + } else { + let endTime = new Date().getTime(); + averageTime = ((endTime - startTime) * 1000) / SPECIAL_BASE_COUNT; + console.info(TAG + " the executeSql_Callback average time is: " + averageTime + " μs"); + expect(averageTime < BASE_LINE).assertTrue(); + done(); + } + }) + } + + let startTime = new Date().getTime(); + executeSqlCallbackPerf(0); + }) +}) diff --git a/relational_store/test/js/rdb/performance/src/RdbStorePromisePerf.js b/relational_store/test/js/rdb/performance/src/RdbStorePromisePerf.js new file mode 100644 index 00000000..0034a9a8 --- /dev/null +++ b/relational_store/test/js/rdb/performance/src/RdbStorePromisePerf.js @@ -0,0 +1,86 @@ +/* + * 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. + */ + +import {describe, beforeAll, beforeEach, afterEach, afterAll, it, expect, Assert} from 'deccjsunit/index'; +import dataRdb from '@ohos.data.rdb'; +import featureAbility from '@ohos.ability.featureAbility'; +import deviceInfo from '@ohos.deviceInfo'; + +const TAG = "[RDBSTORE_PROMISE]"; +const CREATE_TABLE_TEST = "CREATE TABLE IF NOT EXISTS test (id INTEGER PRIMARY KEY AUTOINCREMENT, " + + "name TEXT, age INTEGER, salary REAL, blobType BLOB)"; + +const DB_NAME = "rdbStorePromise.db"; +const STORE_CONFIG = { + name: DB_NAME, +} +let context = featureAbility.getContext(); +var rdbStore = undefined; +const BASE_COUNT = 1000; // loop times +const BASE_LINE_TABLE = 1800; // callback tablet base line +const BASE_LINE_PHONE = 3000; // callback phone base line +const BASE_LINE = (deviceInfo.deviceType == "tablet") ? BASE_LINE_TABLE : BASE_LINE_PHONE; + +describe('rdbStorePromisePerf', function () { + beforeAll(async function () { + console.info(TAG + 'beforeAll'); + rdbStore = await dataRdb.getRdbStore(context, STORE_CONFIG, 1); + }) + beforeEach(async function () { + console.info(TAG + 'beforeEach'); + await rdbStore.executeSql(CREATE_TABLE_TEST, null); + await prepareTestData(); + }) + afterEach(async function () { + console.info(TAG + 'afterEach'); + await rdbStore.executeSql("drop table test"); + }) + afterAll(async function () { + console.info(TAG + 'afterAll'); + rdbStore = null; + await dataRdb.deleteRdbStore(context, DB_NAME); + }) + + async function prepareTestData() { + console.info(TAG + "prepare for query performance test") + var u8 = new Uint8Array([1, 2, 3]) + var valueBucket = { + "name": "zhangsan", + "age": 18, + "salary": 100.5, + "blobType": u8, + } + await dataRdb.insert("test", valueBucket); + } + + console.log(TAG + "*************Unit Test Begin*************"); + + it('SUB_DDM_PERF_RDB_query_Promise_001', 0, async function (done) { + let averageTime = 0; + let predicates = new dataRdb.RdbPredicates("test"); + predicates.equalTo("age", 10); + let startTime = new Date().getTime(); + for (var i = 0; i < BASE_COUNT; i++) { + let resultSet = await rdbStore.query(predicates, []); + resultSet.close(); + } + let endTime = new Date().getTime(); + averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; + console.info(TAG + " the query_Promise average time is: " + averageTime + " μs"); + expect(averageTime < BASE_LINE).assertTrue(); + console.info(TAG + "*************Unit Test End*************"); + done(); + }) +}) diff --git a/relational_store/test/js/rdb/performance/src/RdbStoreSyncPerf.js b/relational_store/test/js/rdb/performance/src/RdbStoreSyncPerf.js new file mode 100644 index 00000000..df364d0c --- /dev/null +++ b/relational_store/test/js/rdb/performance/src/RdbStoreSyncPerf.js @@ -0,0 +1,98 @@ +/* + * 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. + */ + +import {describe, beforeAll, beforeEach, afterEach, afterAll, it, expect, Assert} from 'deccjsunit/index'; +import dataRdb from '@ohos.data.rdb'; +import featureAbility from '@ohos.ability.featureAbility'; +import deviceInfo from '@ohos.deviceInfo'; + +const TAG = "[RDB_SYNC_PROMISE]"; +const CREATE_TABLE_TEST = "CREATE TABLE IF NOT EXISTS test (id INTEGER PRIMARY KEY AUTOINCREMENT, " + + "name TEXT, age INTEGER, salary REAL, blobType BLOB)"; + +const DB_NAME = "rdbSync.db"; +const STORE_CONFIG = { + name: DB_NAME, +} +let context = featureAbility.getContext(); +var rdbStore = undefined; +const BASE_COUNT = 1000; // loop times +const BASE_LINE_TABLE = 2500; // callback tablet base line +const BASE_LINE_PHONE = 3000; // callback phone base line +const BASE_LINE = (deviceInfo.deviceType == "tablet") ? BASE_LINE_TABLE : BASE_LINE_PHONE; + + +describe('rdbStoreSyncPerf', function () { + beforeAll(async function () { + console.info(TAG + 'beforeAll'); + rdbStore = await dataRdb.getRdbStore(context, STORE_CONFIG, 1); + }) + beforeEach(async function () { + console.info(TAG + 'beforeEach'); + }) + afterEach(async function () { + console.info(TAG + 'afterEach'); + }) + afterAll(async function () { + console.info(TAG + 'afterAll'); + rdbStore = null + await dataRdb.deleteRdbStore(context, DB_NAME); + }) + + console.log(TAG + "*************Unit Test Begin*************"); + + it('SUB_DDM_PERF_RDB_version_001', 0, async function (done) { + let averageTime = 0; + let dbVersion = 1; + let startTime = new Date().getTime(); + for (var i = 0; i < BASE_COUNT; i++) { + dbVersion = rdbStore.version; + } + let endTime = new Date().getTime(); + averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; + console.info(TAG + " the version average time is: " + averageTime + " μs"); + expect(averageTime < BASE_LINE).assertTrue(); + done(); + }) + + it('SUB_DDM_PERF_RDB_transaction_commit_001', 0, async function (done) { + let averageTime = 0; + let startTime = new Date().getTime(); + for (var i = 0; i < BASE_COUNT; i++) { + rdbStore.beginTransaction(); + rdbStore.commit(); + } + let endTime = new Date().getTime(); + averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; + console.info(TAG + " the transaction_commit average time is: " + averageTime + " μs"); + expect(averageTime < BASE_LINE).assertTrue(); + done(); + }) + + it('SUB_DDM_PERF_RDB_transaction_rollback_001', 0, async function (done) { + let averageTime = 0; + let startTime = new Date().getTime(); + for (var i = 0; i < BASE_COUNT; i++) { + rdbStore.beginTransaction(); + rdbStore.rollBack(); + } + let endTime = new Date().getTime(); + averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; + console.info(TAG + " the transaction_rollback average time is: " + averageTime + " μs"); + expect(averageTime < BASE_LINE).assertTrue(); + done(); + console.info(TAG + "*************Unit Test End*************"); + }) +}) diff --git a/relational_store/test/js/rdb/performance/src/ResultSetPerf.js b/relational_store/test/js/rdb/performance/src/ResultSetPerf.js new file mode 100644 index 00000000..797d1604 --- /dev/null +++ b/relational_store/test/js/rdb/performance/src/ResultSetPerf.js @@ -0,0 +1,288 @@ +/* + * 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. + */ + +import {describe, beforeAll, beforeEach, afterEach, afterAll, it, expect, Assert} from 'deccjsunit/index'; +import dataRdb from '@ohos.data.rdb'; +import featureAbility from '@ohos.ability.featureAbility'; +import deviceInfo from '@ohos.deviceInfo'; + +const TAG = "[RDB_RESULTSET_PERF]"; +const CREATE_TABLE_TEST = "CREATE TABLE IF NOT EXISTS test (id INTEGER PRIMARY KEY AUTOINCREMENT, " + + "name TEXT, age INTEGER, salary REAL, blobType BLOB)"; + +const DB_NAME = "resultSetPerf.db"; +const STORE_CONFIG = { + name: DB_NAME, +} +let context = featureAbility.getContext(); +var rdbStore = undefined; +const BASE_COUNT = 2000; // loop times +const SPECIAL_BASE_COUNT = 12000; +const BASE_LINE_TABLE = 500; // callback tablet base line +const BASE_LINE_PHONE = 1000; // callback phone base line +const BASE_LINE = (deviceInfo.deviceType == "tablet") ? BASE_LINE_TABLE : BASE_LINE_PHONE; + +describe('resultSetPerf', function () { + beforeAll(async function () { + console.info(TAG + 'beforeAll'); + rdbStore = await dataRdb.getRdbStore(context, STORE_CONFIG, 1); + }) + beforeEach(async function () { + console.info(TAG + 'beforeEach'); + await rdbStore.executeSql(CREATE_TABLE_TEST, null); + await prepareTestData(); + }) + afterEach(async function () { + console.info(TAG + 'afterEach'); + await rdbStore.executeSql("drop table test"); + }) + afterAll(async function () { + console.info(TAG + 'afterAll'); + rdbStore = null; + await dataRdb.deleteRdbStore(context, DB_NAME); + }) + + async function prepareTestData() { + console.info(TAG + "prepare for query performance test"); + var valueBuckets = []; + var u8 = new Uint8Array([1, 2, 3]) + var valueBucket = { + "name": "zhangsan", + "age": 18, + "salary": 100.5, + "blobType": u8, + } + for (let i = 0; i < BASE_COUNT; i++) { + valueBucket.age += i; + valueBuckets.push(valueBucket); + } + await rdbStore.batchInsert("test", valueBuckets) + } + + console.log(TAG + "*************Unit Test Begin*************"); + + it('SUB_DDM_PERF_RDB_ResultSet_GetColumnIndex_001', 0, async function (done) { + let predicates = new dataRdb.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + resultSet.goToFirstRow(); + let startTime = new Date().getTime(); + for (let i = 0; i < BASE_LINE; i++) { + resultSet.getColumnIndex("id"); + } + let endTime = new Date().getTime(); + let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; + console.info(TAG + " the ResultSet_GetColumnIndex average time is: " + averageTime + " μs"); + resultSet.close(); + expect(averageTime < BASE_LINE).assertTrue(); + done(); + }) + + it('SUB_DDM_PERF_RDB_ResultSet_GetColumnName_001', 0, async function (done) { + let predicates = new dataRdb.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + resultSet.goToFirstRow(); + let startTime = new Date().getTime() + for (let i = 0; i < BASE_COUNT; i++) { + resultSet.getColumnName(0); + } + let endTime = new Date().getTime(); + let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; + console.info(TAG + " the ResultSet_GetColumnName average time is: " + averageTime + " μs") + resultSet.close(); + expect(averageTime < BASE_LINE).assertTrue(); + done(); + }) + + it('SUB_DDM_PERF_RDB_ResultSet_GoTo_001', 0, async function (done) { + let predicates = new dataRdb.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + resultSet.goToFirstRow(); + let startTime = new Date().getTime() + for (let i = 0; i < BASE_COUNT; i++) { + resultSet.goTo(i % 2); + } + let endTime = new Date().getTime(); + let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; + console.info(TAG + " the ResultSet_GoTo average time is: " + averageTime + " μs") + resultSet.close(); + expect(averageTime < BASE_LINE).assertTrue(); + done(); + }) + + it('SUB_DDM_PERF_RDB_ResultSet_GoToRow_001', 0, async function (done) { + let predicates = new dataRdb.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + resultSet.goToFirstRow(); + let startTime = new Date().getTime(); + for (let i = 0; i < BASE_COUNT; i++) { + resultSet.goToRow(1); + } + let endTime = new Date().getTime(); + let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; + console.info(TAG + " the ResultSet_GoToRow average time is: " + averageTime + " μs"); + resultSet.close(); + expect(averageTime < BASE_LINE).assertTrue(); + done(); + }) + + it('SUB_DDM_PERF_RDB_ResultSet_GoToFirstRow_001', 0, async function (done) { + let predicates = new dataRdb.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + let startTime = new Date().getTime(); + for (let i = 0; i < BASE_COUNT; i++) { + resultSet.goToFirstRow(); + } + let endTime = new Date().getTime(); + let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; + console.info(TAG + " the ResultSet_GoToFirstRow average time is: " + averageTime + " μs"); + resultSet.close(); + expect(averageTime < BASE_LINE).assertTrue(); + done(); + }) + + it('SUB_DDM_PERF_RDB_ResultSet_GoToLastRow_001', 0, async function (done) { + let predicates = new dataRdb.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + let startTime = new Date().getTime(); + for (let i = 0; i < BASE_COUNT; i++) { + resultSet.goToLastRow(); + } + let endTime = new Date().getTime(); + let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; + console.info(TAG + " the ResultSet_GoToLastRow average time is: " + averageTime + " μs"); + resultSet.close(); + expect(averageTime < BASE_LINE).assertTrue(); + done(); + }) + + it('SUB_DDM_PERF_RDB_ResultSet_GoToNextRow_001', 0, async function (done) { + let predicates = new dataRdb.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + resultSet.goToFirstRow(); + let startTime = new Date().getTime(); + for (let i = 0; i < BASE_COUNT; i++) { + resultSet.goToNextRow(); + } + let endTime = new Date().getTime(); + let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; + console.info(TAG + " the ResultSet_GoToNextRow average time is: " + averageTime + " μs") + resultSet.close(); + expect(averageTime < BASE_LINE).assertTrue(); + done(); + }) + + it('SUB_DDM_PERF_RDB_ResultSet_GoToPreviousRow_001', 0, async function (done) { + let predicates = new dataRdb.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + resultSet.goToLastRow(); + let startTime = new Date().getTime(); + for (let i = 0; i < BASE_COUNT; i++) { + resultSet.goToPreviousRow(); + } + let endTime = new Date().getTime(); + let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; + console.info(TAG + " the ResultSet_GoToPreviousRow average time is: " + averageTime + " μs"); + resultSet.close(); + expect(averageTime < BASE_LINE).assertTrue(); + done(); + }) + + it('SUB_DDM_PERF_RDB_ResultSet_GetBlob_001', 0, async function (done) { + let predicates = new dataRdb.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + let columnIndex = resultSet.getColumnIndex("blobType"); + resultSet.goToFirstRow(); + let startTime = new Date().getTime() + for (let i = 0; i < BASE_COUNT; i++) { + resultSet.getBlob(columnIndex); + } + let endTime = new Date().getTime(); + let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; + console.info(TAG + " the ResultSet_GetBlob average time is: " + averageTime + " μs"); + resultSet.close(); + expect(averageTime < BASE_LINE).assertTrue(); + done(); + }) + + it('SUB_DDM_PERF_RDB_ResultSet_GetString_001', 0, async function (done) { + let predicates = new dataRdb.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + let columnIndex = resultSet.getColumnIndex("name"); + let flag = resultSet.goToFirstRow(); + let startTime = new Date().getTime(); + for (var i = 0; i < SPECIAL_BASE_COUNT; i++) { + resultSet.getString(columnIndex); + } + let endTime = new Date().getTime(); + let averageTime = ((endTime - startTime) * 1000) / SPECIAL_BASE_COUNT; + console.info(TAG + " the ResultSet_GetString average time is: " + averageTime + " μs"); + resultSet.close(); + expect(averageTime < BASE_LINE).assertTrue(); + done() + }) + + it('SUB_DDM_PERF_RDB_ResultSet_GetLong_001', 0, async function (done) { + let predicates = new dataRdb.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + let columnIndex = resultSet.getColumnIndex("age"); + resultSet.goToFirstRow(); + let startTime = new Date().getTime(); + for (let i = 0; i < BASE_COUNT; i++) { + resultSet.getLong(columnIndex); + } + let endTime = new Date().getTime(); + let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; + console.info(TAG + " the ResultSet_GetLong average time is: " + averageTime + " μs") + resultSet.close(); + expect(averageTime < BASE_LINE).assertTrue(); + done(); + }) + + it('SUB_DDM_PERF_RDB_ResultSet_GetDouble_001', 0, async function (done) { + let predicates = new dataRdb.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + let columnIndex = resultSet.getColumnIndex("salary"); + resultSet.goToFirstRow(); + let startTime = new Date().getTime() + for (let i = 0; i < BASE_COUNT; i++) { + resultSet.getDouble(columnIndex); + } + let endTime = new Date().getTime(); + let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; + console.info(TAG + " the ResultSet_GetDouble average time is: " + averageTime + " μs") + resultSet.close(); + expect(averageTime < BASE_LINE).assertTrue(); + done(); + }) + + it('SUB_DDM_PERF_RDB_ResultSet_IsColumnNull_001', 0, async function (done) { + let predicates = new dataRdb.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + let columnIndex = resultSet.getColumnIndex("salary"); + resultSet.goToFirstRow(); + let startTime = new Date().getTime() + for (let i = 0; i < BASE_COUNT; i++) { + resultSet.isColumnNull(columnIndex); + } + let endTime = new Date().getTime(); + let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; + console.info(TAG + " the ResultSet_IsColumnNull average time is: " + averageTime + " μs"); + resultSet.close(); + expect(averageTime < BASE_LINE).assertTrue(); + done(); + }) + + console.info(TAG + "*************Unit Test End*************"); +}) \ No newline at end of file diff --git a/relational_store/test/js/rdb/unittest/src/RdbstoreBackupRestoreWithFAContextJsunit.test.js b/relational_store/test/js/rdb/unittest/src/RdbstoreBackupRestoreWithFAContextJsunit.test.js new file mode 100644 index 00000000..4b174d56 --- /dev/null +++ b/relational_store/test/js/rdb/unittest/src/RdbstoreBackupRestoreWithFAContextJsunit.test.js @@ -0,0 +1,245 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import {describe, beforeAll, beforeEach, afterEach, afterAll, it, expect} from 'deccjsunit/index' +import data_rdb from '@ohos.data.rdb' +import ability_featureAbility from '@ohos.ability.featureAbility' +import fileio from '@ohos.fileio' + +const TAG = "[RDB_JSKITS_TEST]" +const CREATE_TABLE_TEST = "CREATE TABLE IF NOT EXISTS test (" + "id INTEGER PRIMARY KEY AUTOINCREMENT, " + + "name TEXT NOT NULL, " + "age INTEGER, " + "salary REAL, " + "blobType BLOB)" +const DATABASE_DIR = "/data/storage/el2/database/entry/rdb/" +var rdbStore +var context +const STORE_CONFIG = { + name: "BackupResotreTest.db", +} +const DATABASE_BACKUP_NAME = "Backup.db" + +async function CreatRdbStore(context, STORE_CONFIG) { + let rdbStore = await data_rdb.getRdbStore(context, STORE_CONFIG, 1) + await rdbStore.executeSql(CREATE_TABLE_TEST, null) + let u8 = new Uint8Array([1, 2, 3]) + { + const valueBucket = { + "name": "zhangsan", + "age": 18, + "salary": 100.5, + "blobType": u8, + } + await rdbStore.insert("test", valueBucket) + } + { + const valueBucket = { + "name": "lisi", + "age": 28, + "salary": 100.5, + "blobType": u8, + } + await rdbStore.insert("test", valueBucket) + } + { + const valueBucket = { + "name": "wangwu", + "age": 38, + "salary": 90.0, + "blobType": u8, + } + await rdbStore.insert("test", valueBucket) + } + return rdbStore +} + +async function BackupTest(backupName) { + try { + let promiseRestore = rdbStore.backup(backupName) + promiseRestore.then(() => { + expect(false).assertTrue() + }).catch((err) => { + expect(true).assertTrue() + }) + await promiseRestore + } catch { + expect(true).assertTrue() + } + + rdbStore = null +} + +async function RestoreTest(restoreName) { + try { + let promiseRestore = rdbStore.restore(restoreName) + promiseRestore.then(() => { + expect(false).assertTrue() + }).catch((err) => { + expect(true).assertTrue() + }) + await promiseRestore + } catch { + expect(true).assertTrue() + } + + rdbStore = null +} + +describe('rdbStoreBackupRestoreWithFAContextTest', function () { + beforeAll(async function () { + console.info(TAG + 'beforeAll') + }) + + beforeEach(async function () { + console.info(TAG + 'beforeEach') + context = ability_featureAbility.getContext() + rdbStore = await CreatRdbStore(context, STORE_CONFIG) + }) + + afterEach(async function () { + console.info(TAG + 'afterEach') + rdbStore = null + await data_rdb.deleteRdbStore(context, STORE_CONFIG.name) + await data_rdb.deleteRdbStore(context, DATABASE_BACKUP_NAME) + }) + + afterAll(async function () { + console.info(TAG + 'afterAll') + }) + + console.log(TAG + "*************Unit Test Begin*************") + + /** + * @tc.name RDB Backup Restore test + * @tc.number SUB_DDM_RDB_JS_RdbBackupRestoreTest_0010 + * @tc.desc RDB backup and restore function test + */ + it('RdbBackupRestoreTest_0010', 0, async function (done) { + await console.log(TAG + "************* RdbBackupRestoreTest_0010 start *************") + + // RDB backup function test + let promiseBackup = rdbStore.backup(DATABASE_BACKUP_NAME) + promiseBackup.then(() => { + try { + fileio.accessSync(DATABASE_DIR + DATABASE_BACKUP_NAME) + fileio.accessSync(DATABASE_DIR + STORE_CONFIG.name) + } catch (err) { + expect(false).assertTrue() + } + }).catch((err) => { + expect(false).assertTrue() + }) + await promiseBackup + + // RDB restore function test + let promiseRestore = rdbStore.restore(DATABASE_BACKUP_NAME) + promiseRestore.then(() => { + try { + fileio.accessSync(DATABASE_DIR + DATABASE_BACKUP_NAME) + expect(false).assertTrue() + } catch (err) { + expect(true).assertTrue() + } + + try { + fileio.accessSync(DATABASE_DIR + STORE_CONFIG.name) + expect(true).assertTrue() + } catch (err) { + expect(false).assertTrue() + } + }).catch((err) => { + expect(false).assertTrue() + }) + await promiseRestore + + // RDB after restored, data query test + let predicates = new data_rdb.RdbPredicates("test") + predicates.equalTo("name", "zhangsan") + let resultSet = await rdbStore.query(predicates) + try { + console.log(TAG + "After restore resultSet query done") + expect(true).assertEqual(resultSet.goToFirstRow()) + const id = resultSet.getLong(resultSet.getColumnIndex("id")) + const name = resultSet.getString(resultSet.getColumnIndex("name")) + const blobType = resultSet.getBlob(resultSet.getColumnIndex("blobType")) + expect(1).assertEqual(id) + expect("zhangsan").assertEqual(name) + expect(1).assertEqual(blobType[0]) + } catch (err) { + expect(false).assertTrue() + } + resultSet.close() + resultSet = null + done() + await console.log(TAG + "************* RdbBackupRestoreTest_0010 end *************") + }) + + /** + * @tc.name RDB Backup test + * @tc.number SUB_DDM_RDB_JS_RdbBackupRestoreTest_0020 + * @tc.desc RDB backup function test + */ + it('RdbBackupRestoreTest_0020', 0, async function (done) { + await console.log(TAG + "************* RdbBackupRestoreTest_0020 start *************") + // RDB backup function test, backup file name empty + BackupTest("") + + // RDB backup function test, backup file name already exists + BackupTest(STORE_CONFIG.name) + + done() + await console.log(TAG + "************* RdbBackupRestoreTest_0020 end *************") + }) + + /** + * @tc.name RDB BackupRestore test + * @tc.number SUB_DDM_RDB_JS_RdbBackupRestoreTest_0030 + * @tc.desc RDB restore function test + */ + it('RdbBackupRestoreTest_0030', 0, async function (done) { + await console.log(TAG + "************* RdbBackupRestoreTest_0030 start *************") + await rdbStore.backup(DATABASE_BACKUP_NAME) + + // RDB restore function test, backup file name empty + RestoreTest("") + + // RDB restore function test, backup file is specified to database name + RestoreTest(STORE_CONFIG.name) + + done() + await console.log(TAG + "************* RdbBackupRestoreTest_0030 end *************") + }) + + /** + * @tc.name RDB BackupRestore test + * @tc.number SUB_DDM_RDB_JS_RdbBackupRestoreTest_0040 + * @tc.desc RDB restore function test + */ + it('RdbBackupRestoreTest_0040', 0, async function (done) { + await console.log(TAG + "************* RdbBackupRestoreTest_0040 start *************") + let dbName = "notExistName.db" + + // RDB restore function test, backup file does not exists + try { + fileio.accessSync(DATABASE_DIR + dbName) + expect(false).assertTrue() + } catch { + RestoreTest(dbName) + } + + done() + await console.log(TAG + "************* RdbBackupRestoreTest_0040 end *************") + }) + + console.log(TAG + "*************Unit Test End*************") + } +) diff --git a/relational_store/test/js/relationalstore/BUILD.gn b/relational_store/test/js/relationalstore/BUILD.gn index 0d590223..27abd8a1 100644 --- a/relational_store/test/js/relationalstore/BUILD.gn +++ b/relational_store/test/js/relationalstore/BUILD.gn @@ -20,4 +20,11 @@ group("unittest") { deps += [ "unittest/src:unittest" ] } + +group("performancetest") { + testonly = true + deps = [] + + deps += [ "performance/src:RelationalStorePerfJsTest" ] +} ############################################################################### diff --git a/relational_store/test/js/relationalstore/performance/src/BUILD.gn b/relational_store/test/js/relationalstore/performance/src/BUILD.gn index d13758d2..d0814abe 100644 --- a/relational_store/test/js/relationalstore/performance/src/BUILD.gn +++ b/relational_store/test/js/relationalstore/performance/src/BUILD.gn @@ -13,9 +13,9 @@ import("//build/test.gni") -module_output_path = "relational_store/oh_perf" +module_output_path = "relational_store/performance" -ohos_js_unittest("OHRdbPerfJsTest") { +ohos_js_unittest("RelationalStorePerfJsTest") { module_out_path = module_output_path hap_profile = "../config.json" diff --git a/relational_store/test/js/relationalstore/performance/src/PredicatestPerf.js b/relational_store/test/js/relationalstore/performance/src/PredicatestPerf.js index 47c0f77b..da7fd556 100644 --- a/relational_store/test/js/relationalstore/performance/src/PredicatestPerf.js +++ b/relational_store/test/js/relationalstore/performance/src/PredicatestPerf.js @@ -13,21 +13,12 @@ * limitations under the License. */ -import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect, Assert } from 'deccjsunit/index'; -import dataRdb from '@ohos.data.rdb'; -import featureAbility from '@ohos.ability.featureAbility'; +import {describe, beforeAll, beforeEach, afterEach, afterAll, it, expect, Assert} from 'deccjsunit/index'; +import dataRdb from '@ohos.data.relationalStore'; import deviceInfo from '@ohos.deviceInfo'; const TAG = "[RDB_PREDICATES_PERF]"; -const CREATE_TABLE_TEST = "CREATE TABLE IF NOT EXISTS test (id INTEGER PRIMARY KEY AUTOINCREMENT, " -+ "name TEXT, age INTEGER, salary REAL, blobType BLOB)"; - -const DB_NAME = "predicatesPerf.db"; -const STORE_CONFIG = { - name: DB_NAME, -} -let context = featureAbility.getContext(); -var rdbStore = undefined; + const BASE_COUNT = 2000; // loop times const BASE_COUNT_FIRST = 200; const BASE_COUNT_SECOND = 10; @@ -36,480 +27,480 @@ const BASE_LINE_PHONE = 1000; // callback phone base line const BASE_LINE = (deviceInfo.deviceType == "tablet") ? BASE_LINE_TABLE : BASE_LINE_PHONE; describe('predicatesPerf', function () { - beforeAll(async function () { - console.info(TAG + 'beforeAll'); - }) - beforeEach(async function () { - console.info(TAG + 'beforeEach'); - }) - afterEach(async function () { - console.info(TAG + 'afterEach'); - }) - afterAll(async function () { - console.info(TAG + 'afterAll'); - }) - - console.log(TAG + "*************Unit Test Begin*************"); - - it('SUB_DDM_PERF_RDB_Predicates_inDevices_001', 0, async function (done) { - let startTime = new Date().getTime(); - for (let i = 0; i < BASE_COUNT_FIRST; i++) { - let predicates = new dataRdb.RdbPredicates("test"); - for (let j = 0; j < BASE_COUNT_SECOND; j++) { - predicates.inDevices(['123']); - } - } - let endTime = new Date().getTime(); - let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; - console.info(TAG + " the Predicates_inDevices average time is: " + averageTime + " μs"); - expect(averageTime < BASE_LINE).assertTrue(); - done(); - }) - - it('SUB_DDM_PERF_RDB_Predicates_inAllDevices_001', 0, async function (done) { - let startTime = new Date().getTime(); - for (let i = 0; i < BASE_COUNT_FIRST; i++) { - let predicates = new dataRdb.RdbPredicates("test"); - for (let j = 0; j < BASE_COUNT_SECOND; j++) { - predicates.inAllDevices(); - } - } - let endTime = new Date().getTime(); - let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; - console.info(TAG + " the Predicates_inAllDevices average time is: " + averageTime + " μs"); - expect(averageTime < BASE_LINE).assertTrue(); - done(); - }) - - it('SUB_DDM_PERF_RDB_Predicates_equalTo_001', 0, async function (done) { - let startTime = new Date().getTime(); - for (let i = 0; i < BASE_COUNT_FIRST; i++) { - let predicates = new dataRdb.RdbPredicates("test"); - for (let j = 0; j < BASE_COUNT_SECOND; j++) { - predicates.equalTo("name", "lisi"); - } - } - let endTime = new Date().getTime(); - let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; - console.info(TAG + " the Predicates_equalTo average time is: " + averageTime + " μs"); - expect(averageTime < BASE_LINE).assertTrue(); - done(); - }) - - it('SUB_DDM_PERF_RDB_Predicates_notEqualTo_001', 0, async function (done) { - let startTime = new Date().getTime(); - for (let i = 0; i < BASE_COUNT_FIRST; i++) { - let predicates = new dataRdb.RdbPredicates("test"); - for (let j = 0; j < BASE_COUNT_SECOND; j++) { - predicates.notEqualTo("name", "lisi"); - } - } - let endTime = new Date().getTime(); - let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; - console.info(TAG + " the Predicates_notEqualTo average time is: " + averageTime + " μs"); - expect(averageTime < BASE_LINE).assertTrue(); - done(); - }) - - it('SUB_DDM_PERF_RDB_Predicates_beginWrap_001', 0, async function (done) { - let startTime = new Date().getTime(); - for (let i = 0; i < BASE_COUNT_FIRST; i++) { - let predicates = new dataRdb.RdbPredicates("test"); - for (let j = 0; j < BASE_COUNT_SECOND; j++) { - predicates.beginWrap(); - } - } - let endTime = new Date().getTime(); - let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; - console.info(TAG + " the Predicates_beginWrap average time is: " + averageTime + " μs"); - expect(averageTime < BASE_LINE).assertTrue(); - done(); - }) - - it('SUB_DDM_PERF_RDB_Predicates_endWrap_001', 0, async function (done) { - let startTime = new Date().getTime(); - for (let i = 0; i < BASE_COUNT_FIRST; i++) { - let predicates = new dataRdb.RdbPredicates("test"); - for (let j = 0; j < BASE_COUNT_SECOND; j++) { - predicates.equalTo("name", "lisi"); - predicates.endWrap(); - } - } - let endTime = new Date().getTime(); - let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; - console.info(TAG + " the Predicates_endWrap average time is: " + averageTime + " μs"); - expect(averageTime < BASE_LINE).assertTrue(); - done(); - }) - - it('SUB_DDM_PERF_RDB_Predicates_or_001', 0, async function (done) { - let startTime = new Date().getTime(); - for (let i = 0; i < BASE_COUNT_FIRST; i++) { - let predicates = new dataRdb.RdbPredicates("test"); - for (let j = 0; j < BASE_COUNT_SECOND; j++) { - predicates.equalTo("name", "lisi"); - predicates.or(); - predicates.equalTo("age", 18); - } - } - let endTime = new Date().getTime(); - let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; - console.info(TAG + " the Predicates_or average time is: " + averageTime + " μs"); - expect(averageTime < BASE_LINE).assertTrue(); - done(); - }) - - it('SUB_DDM_PERF_RDB_Predicates_and_001', 1, async function (done) { - let startTime = new Date().getTime(); - for (let i = 0; i < BASE_COUNT_FIRST; i++) { - let predicates = new dataRdb.RdbPredicates("test"); - for (let j = 0; j < BASE_COUNT_SECOND; j++) { - predicates.equalTo("name", "lisi"); - predicates.and(); - predicates.equalTo("name", "zs"); - } - } - let endTime = new Date().getTime(); - let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; - console.info(TAG + " the Predicates_and average time is: " + averageTime + " μs"); - expect(averageTime < BASE_LINE).assertTrue(); - done(); - }) - - it('SUB_DDM_PERF_RDB_Predicates_contains_001', 0, async function (done) { - let startTime = new Date().getTime(); - for (let i = 0; i < BASE_COUNT_FIRST; i++) { - let predicates = new dataRdb.RdbPredicates("test"); - for (let j = 0; j < BASE_COUNT_SECOND; j++) { - predicates.contains("name", "lisi"); - } - } - let endTime = new Date().getTime(); - let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; - console.info(TAG + " the Predicates_contains average time is: " + averageTime + " μs"); - expect(averageTime < BASE_LINE).assertTrue(); - done(); - }) - - it('SUB_DDM_PERF_RDB_Predicates_beginsWith_001', 0, async function (done) { - let startTime = new Date().getTime(); - for (let i = 0; i < BASE_COUNT_FIRST; i++) { - let predicates = new dataRdb.RdbPredicates("test"); - for (let j = 0; j < BASE_COUNT_SECOND; j++) { - predicates.beginsWith("name", "lisi"); - } - } - let endTime = new Date().getTime(); - let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; - console.info(TAG + " the Predicates_beginsWith average time is: " + averageTime + " μs"); - expect(averageTime < BASE_LINE).assertTrue(); - done(); - }) - - it('SUB_DDM_PERF_RDB_Predicates_endWith_001', 0, async function (done) { - let startTime = new Date().getTime(); - for (let i = 0; i < BASE_COUNT_FIRST; i++) { - let predicates = new dataRdb.RdbPredicates("test"); - for (let j = 0; j < BASE_COUNT_SECOND; j++) { - predicates.endsWith("name", "lisi"); - } - } - let endTime = new Date().getTime(); - let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; - console.info(TAG + " the Predicates_endWith average time is: " + averageTime + " μs"); - expect(averageTime < BASE_LINE).assertTrue(); - done(); - }) - - it('SUB_DDM_PERF_RDB_Predicates_isNull_001', 0, async function (done) { - let startTime = new Date().getTime(); - for (let i = 0; i < BASE_COUNT_FIRST; i++) { - let predicates = new dataRdb.RdbPredicates("test"); - for (let j = 0; j < BASE_COUNT_SECOND; j++) { - predicates.isNull("name"); - } - } - let endTime = new Date().getTime(); - let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; - console.info(TAG + " the Predicates_isNull average time is: " + averageTime + " μs"); - expect(averageTime < BASE_LINE).assertTrue(); - done(); - }) - - it('SUB_DDM_PERF_RDB_Predicates_isNotNull_001', 0, async function (done) { - let startTime = new Date().getTime(); - for (let i = 0; i < BASE_COUNT_FIRST; i++) { - let predicates = new dataRdb.RdbPredicates("test"); - for (let j = 0; j < BASE_COUNT_SECOND; j++) { - predicates.isNotNull("name"); - } - } - let endTime = new Date().getTime(); - let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; - console.info(TAG + " the Predicates_isNotNull average time is: " + averageTime + " μs"); - expect(averageTime < BASE_LINE).assertTrue(); - done(); - }) - - it('SUB_DDM_PERF_RDB_Predicates_like_001', 0, async function (done) { - let startTime = new Date().getTime(); - for (let i = 0; i < BASE_COUNT_FIRST; i++) { - let predicates = new dataRdb.RdbPredicates("test"); - for (let j = 0; j < BASE_COUNT_SECOND; j++) { - predicates.like("name", "li"); - } - } - let endTime = new Date().getTime(); - let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; - console.info(TAG + " the Predicates_like average time is: " + averageTime + " μs"); - expect(averageTime < BASE_LINE).assertTrue(); - done(); - }) - - it('SUB_DDM_PERF_RDB_Predicates_glob_001', 0, async function (done) { - let startTime = new Date().getTime(); - for (let i = 0; i < BASE_COUNT_FIRST; i++) { - let predicates = new dataRdb.RdbPredicates("test"); - for (let j = 0; j < BASE_COUNT_SECOND; j++) { - predicates.glob("name", "li"); - } - } - let endTime = new Date().getTime(); - let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; - console.info(TAG + " the Predicates_glob average time is: " + averageTime + " μs"); - expect(averageTime < BASE_LINE).assertTrue(); - done(); - }) - - it('SUB_DDM_PERF_RDB_Predicates_between_001', 0, async function (done) { - let startTime = new Date().getTime(); - for (let i = 0; i < BASE_COUNT_FIRST; i++) { - let predicates = new dataRdb.RdbPredicates("test"); - for (let j = 0; j < BASE_COUNT_SECOND; j++) { - predicates.between("age", 1, 100); - } - } - let endTime = new Date().getTime(); - let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; - console.info(TAG + " the Predicates_between average time is: " + averageTime + " μs"); - expect(averageTime < BASE_LINE).assertTrue(); - done(); - }) - - it('SUB_DDM_PERF_RDB_Predicates_notBetween_001', 0, async function (done) { - let startTime = new Date().getTime(); - for (let i = 0; i < BASE_COUNT_FIRST; i++) { - let predicates = new dataRdb.RdbPredicates("test"); - for (let j = 0; j < BASE_COUNT_SECOND; j++) { - predicates.notBetween("age", 1, 100); - } - } - let endTime = new Date().getTime(); - let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; - console.info(TAG + " the Predicates_notBetween average time is: " + averageTime + " μs"); - expect(averageTime < BASE_LINE).assertTrue(); - done(); - }) - - it('SUB_DDM_PERF_RDB_Predicates_greaterThan_001', 0, async function (done) { - let startTime = new Date().getTime(); - for (let i = 0; i < BASE_COUNT_FIRST; i++) { - let predicates = new dataRdb.RdbPredicates("test"); - for (let j = 0; j < BASE_COUNT_SECOND; j++) { - predicates.greaterThan("age", 1); - } - } - let endTime = new Date().getTime(); - let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; - console.info(TAG + " the Predicates_greaterThan average time is: " + averageTime + " μs"); - expect(averageTime < BASE_LINE).assertTrue(); - done(); - }) - - it('SUB_DDM_PERF_RDB_Predicates_lessThan_001', 0, async function (done) { - let startTime = new Date().getTime(); - for (let i = 0; i < BASE_COUNT_FIRST; i++) { - let predicates = new dataRdb.RdbPredicates("test"); - for (let j = 0; j < BASE_COUNT_SECOND; j++) { - predicates.lessThan("age", 1000); - } - } - let endTime = new Date().getTime(); - let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; - console.info(TAG + " the Predicates_lessThan average time is: " + averageTime + " μs"); - expect(averageTime < BASE_LINE).assertTrue(); - done(); - }) - - it('SUB_DDM_PERF_RDB_Predicates_greaterThanOrEqualTo_001', 0, async function (done) { - let startTime = new Date().getTime(); - for (let i = 0; i < BASE_COUNT_FIRST; i++) { - let predicates = new dataRdb.RdbPredicates("test"); - for (let j = 0; j < BASE_COUNT_SECOND; j++) { - predicates.greaterThanOrEqualTo("age", 1000); - } - } - let endTime = new Date().getTime(); - let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; - console.info(TAG + " the Predicates_greaterThanOrEqualTo average time is: " + averageTime + " μs"); - expect(averageTime < BASE_LINE).assertTrue(); - done(); - }) - - it('SUB_DDM_PERF_RDB_Predicates_lessThanOrEqualTo_001', 0, async function (done) { - let startTime = new Date().getTime(); - for (let i = 0; i < BASE_COUNT_FIRST; i++) { - let predicates = new dataRdb.RdbPredicates("test"); - for (let j = 0; j < BASE_COUNT_SECOND; j++) { - predicates.lessThanOrEqualTo("age", 1000); - } - } - let endTime = new Date().getTime(); - let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; - console.info(TAG + " the Predicates_lessThanOrEqualTo average time is: " + averageTime + " μs"); - expect(averageTime < BASE_LINE).assertTrue(); - done(); - }) - - it('SUB_DDM_PERF_RDB_Predicates_orderByAsc_001', 0, async function (done) { - let startTime = new Date().getTime(); - for (let i = 0; i < BASE_COUNT_FIRST; i++) { - let predicates = new dataRdb.RdbPredicates("test"); - for (let j = 0; j < BASE_COUNT_SECOND; j++) { - predicates.orderByAsc("name"); - } - } - let endTime = new Date().getTime(); - let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; - console.info(TAG + " the Predicates_orderByAsc average time is: " + averageTime + " μs"); - expect(averageTime < BASE_LINE).assertTrue(); - done(); - }) - - it('SUB_DDM_PERF_RDB_Predicates_orderByDesc_001', 0, async function (done) { - let startTime = new Date().getTime(); - for (let i = 0; i < BASE_COUNT_FIRST; i++) { - let predicates = new dataRdb.RdbPredicates("test"); - for (let j = 0; j < BASE_COUNT_SECOND; j++) { - predicates.orderByDesc("name"); - } - } - let endTime = new Date().getTime(); - let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; - console.info(TAG + " the Predicates_orderByDesc average time is: " + averageTime + " μs"); - expect(averageTime < BASE_LINE).assertTrue(); - done(); - }) - - it('SUB_DDM_PERF_RDB_Predicates_distinct_001', 0, async function (done) { - let startTime = new Date().getTime(); - for (let i = 0; i < BASE_COUNT_FIRST; i++) { - let predicates = new dataRdb.RdbPredicates("test"); - for (let j = 0; j < BASE_COUNT_SECOND; j++) { - predicates.distinct(); - } - } - let endTime = new Date().getTime(); - let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; - console.info(TAG + " the Predicates_distinct average time is: " + averageTime + " μs"); - expect(averageTime < BASE_LINE).assertTrue(); - done(); - }) - - it('SUB_DDM_PERF_RDB_Predicates_limitAs_001', 0, async function (done) { - let startTime = new Date().getTime(); - for (let i = 0; i < BASE_COUNT; i++) { - let predicates = new dataRdb.RdbPredicates("test"); - predicates.limitAs(6); - } - let endTime = new Date().getTime(); - let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; - console.info(TAG + " the Predicates_limitAs average time is: " + averageTime + " μs"); - expect(averageTime < BASE_LINE).assertTrue(); - done(); - }) - - it('SUB_DDM_PERF_RDB_Predicates_offsetAs_001', 0, async function (done) { - let startTime = new Date().getTime(); - for (let i = 0; i < BASE_COUNT; i++) { - let predicates = new dataRdb.RdbPredicates("test"); - predicates.offsetAs(6); - } - let endTime = new Date().getTime(); - let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; - console.info(TAG + " the Predicates_offsetAs average time is: " + averageTime + " μs"); - expect(averageTime < BASE_LINE).assertTrue(); - done(); - }) - - it('SUB_DDM_PERF_RDB_Predicates_groupBy_001', 0, async function (done) { - let nameArr = new Array(); - nameArr.push("id"); - nameArr.push("name"); - let startTime = new Date().getTime(); - for (let i = 0; i < BASE_COUNT_FIRST; i++) { - let predicates = new dataRdb.RdbPredicates("test"); - for (let j = 0; j < BASE_COUNT_SECOND; j++) { - predicates.groupBy(nameArr); - } - } - let endTime = new Date().getTime(); - let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; - console.info(TAG + " the Predicates_groupBy average time is: " + averageTime + " μs"); - expect(averageTime < BASE_LINE).assertTrue(); - done(); - }) - - it('SUB_DDM_PERF_RDB_Predicates_indexedBy_001', 0, async function (done) { - let startTime = new Date().getTime(); - for (let i = 0; i < BASE_COUNT_FIRST; i++) { - let predicates = new dataRdb.RdbPredicates("test"); - for (let j = 0; j < BASE_COUNT_SECOND; j++) { - predicates.indexedBy("name"); - } - } - let endTime = new Date().getTime(); - let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; - console.info(TAG + " the Predicates_indexedBy average time is: " + averageTime + " μs"); - expect(averageTime < BASE_LINE).assertTrue(); - done(); - }) - - it('SUB_DDM_PERF_RDB_Predicates_in_001', 0, async function (done) { - let nameArr = new Array(); - nameArr.push("id"); - nameArr.push("name"); - let startTime = new Date().getTime(); - for (let i = 0; i < BASE_COUNT_FIRST; i++) { - let predicates = new dataRdb.RdbPredicates("test"); - for (let j = 0; j < BASE_COUNT_SECOND; j++) { - predicates.in("name", nameArr); - } - } - let endTime = new Date().getTime(); - let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; - console.info(TAG + " the Predicates_in average time is: " + averageTime + " μs"); - expect(averageTime < BASE_LINE).assertTrue(); - done(); - }) - - it('SUB_DDM_PERF_RDB_Predicates_notIn(_001', 0, async function (done) { - let nameArr = new Array(); - nameArr.push("zhangsan"); - nameArr.push("lisi"); - let startTime = new Date().getTime(); - for (let i = 0; i < BASE_COUNT_FIRST; i++) { - let predicates = new dataRdb.RdbPredicates("test"); - for (let j = 0; j < BASE_COUNT_SECOND; j++) { - predicates.notIn("name", nameArr); - } - } - let endTime = new Date().getTime(); - let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; - console.info(TAG + " the Predicates_notIn average time is: " + averageTime + " μs"); - expect(averageTime < BASE_LINE).assertTrue(); - done(); - }) - - console.info(TAG + "*************Unit Test End*************") + beforeAll(async function () { + console.info(TAG + 'beforeAll'); + }) + beforeEach(async function () { + console.info(TAG + 'beforeEach'); + }) + afterEach(async function () { + console.info(TAG + 'afterEach'); + }) + afterAll(async function () { + console.info(TAG + 'afterAll'); + }) + + console.log(TAG + "*************Unit Test Begin*************"); + + it('SUB_DDM_PERF_RDB_Predicates_inDevices_001', 0, async function (done) { + let startTime = new Date().getTime(); + for (let i = 0; i < BASE_COUNT_FIRST; i++) { + let predicates = new dataRdb.RdbPredicates("test"); + for (let j = 0; j < BASE_COUNT_SECOND; j++) { + predicates.inDevices(['123']); + } + } + let endTime = new Date().getTime(); + let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; + console.info(TAG + " the Predicates_inDevices average time is: " + averageTime + " μs"); + expect(averageTime < BASE_LINE).assertTrue(); + done(); + }) + + it('SUB_DDM_PERF_RDB_Predicates_inAllDevices_001', 0, async function (done) { + let startTime = new Date().getTime(); + for (let i = 0; i < BASE_COUNT_FIRST; i++) { + let predicates = new dataRdb.RdbPredicates("test"); + for (let j = 0; j < BASE_COUNT_SECOND; j++) { + predicates.inAllDevices(); + } + } + let endTime = new Date().getTime(); + let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; + console.info(TAG + " the Predicates_inAllDevices average time is: " + averageTime + " μs"); + expect(averageTime < BASE_LINE).assertTrue(); + done(); + }) + + it('SUB_DDM_PERF_RDB_Predicates_equalTo_001', 0, async function (done) { + let startTime = new Date().getTime(); + for (let i = 0; i < BASE_COUNT_FIRST; i++) { + let predicates = new dataRdb.RdbPredicates("test"); + for (let j = 0; j < BASE_COUNT_SECOND; j++) { + predicates.equalTo("name", "lisi"); + } + } + let endTime = new Date().getTime(); + let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; + console.info(TAG + " the Predicates_equalTo average time is: " + averageTime + " μs"); + expect(averageTime < BASE_LINE).assertTrue(); + done(); + }) + + it('SUB_DDM_PERF_RDB_Predicates_notEqualTo_001', 0, async function (done) { + let startTime = new Date().getTime(); + for (let i = 0; i < BASE_COUNT_FIRST; i++) { + let predicates = new dataRdb.RdbPredicates("test"); + for (let j = 0; j < BASE_COUNT_SECOND; j++) { + predicates.notEqualTo("name", "lisi"); + } + } + let endTime = new Date().getTime(); + let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; + console.info(TAG + " the Predicates_notEqualTo average time is: " + averageTime + " μs"); + expect(averageTime < BASE_LINE).assertTrue(); + done(); + }) + + it('SUB_DDM_PERF_RDB_Predicates_beginWrap_001', 0, async function (done) { + let startTime = new Date().getTime(); + for (let i = 0; i < BASE_COUNT_FIRST; i++) { + let predicates = new dataRdb.RdbPredicates("test"); + for (let j = 0; j < BASE_COUNT_SECOND; j++) { + predicates.beginWrap(); + } + } + let endTime = new Date().getTime(); + let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; + console.info(TAG + " the Predicates_beginWrap average time is: " + averageTime + " μs"); + expect(averageTime < BASE_LINE).assertTrue(); + done(); + }) + + it('SUB_DDM_PERF_RDB_Predicates_endWrap_001', 0, async function (done) { + let startTime = new Date().getTime(); + for (let i = 0; i < BASE_COUNT_FIRST; i++) { + let predicates = new dataRdb.RdbPredicates("test"); + for (let j = 0; j < BASE_COUNT_SECOND; j++) { + predicates.equalTo("name", "lisi"); + predicates.endWrap(); + } + } + let endTime = new Date().getTime(); + let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; + console.info(TAG + " the Predicates_endWrap average time is: " + averageTime + " μs"); + expect(averageTime < BASE_LINE).assertTrue(); + done(); + }) + + it('SUB_DDM_PERF_RDB_Predicates_or_001', 0, async function (done) { + let startTime = new Date().getTime(); + for (let i = 0; i < BASE_COUNT_FIRST; i++) { + let predicates = new dataRdb.RdbPredicates("test"); + for (let j = 0; j < BASE_COUNT_SECOND; j++) { + predicates.equalTo("name", "lisi"); + predicates.or(); + predicates.equalTo("age", 18); + } + } + let endTime = new Date().getTime(); + let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; + console.info(TAG + " the Predicates_or average time is: " + averageTime + " μs"); + expect(averageTime < BASE_LINE).assertTrue(); + done(); + }) + + it('SUB_DDM_PERF_RDB_Predicates_and_001', 1, async function (done) { + let startTime = new Date().getTime(); + for (let i = 0; i < BASE_COUNT_FIRST; i++) { + let predicates = new dataRdb.RdbPredicates("test"); + for (let j = 0; j < BASE_COUNT_SECOND; j++) { + predicates.equalTo("name", "lisi"); + predicates.and(); + predicates.equalTo("name", "zs"); + } + } + let endTime = new Date().getTime(); + let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; + console.info(TAG + " the Predicates_and average time is: " + averageTime + " μs"); + expect(averageTime < BASE_LINE).assertTrue(); + done(); + }) + + it('SUB_DDM_PERF_RDB_Predicates_contains_001', 0, async function (done) { + let startTime = new Date().getTime(); + for (let i = 0; i < BASE_COUNT_FIRST; i++) { + let predicates = new dataRdb.RdbPredicates("test"); + for (let j = 0; j < BASE_COUNT_SECOND; j++) { + predicates.contains("name", "lisi"); + } + } + let endTime = new Date().getTime(); + let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; + console.info(TAG + " the Predicates_contains average time is: " + averageTime + " μs"); + expect(averageTime < BASE_LINE).assertTrue(); + done(); + }) + + it('SUB_DDM_PERF_RDB_Predicates_beginsWith_001', 0, async function (done) { + let startTime = new Date().getTime(); + for (let i = 0; i < BASE_COUNT_FIRST; i++) { + let predicates = new dataRdb.RdbPredicates("test"); + for (let j = 0; j < BASE_COUNT_SECOND; j++) { + predicates.beginsWith("name", "lisi"); + } + } + let endTime = new Date().getTime(); + let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; + console.info(TAG + " the Predicates_beginsWith average time is: " + averageTime + " μs"); + expect(averageTime < BASE_LINE).assertTrue(); + done(); + }) + + it('SUB_DDM_PERF_RDB_Predicates_endWith_001', 0, async function (done) { + let startTime = new Date().getTime(); + for (let i = 0; i < BASE_COUNT_FIRST; i++) { + let predicates = new dataRdb.RdbPredicates("test"); + for (let j = 0; j < BASE_COUNT_SECOND; j++) { + predicates.endsWith("name", "lisi"); + } + } + let endTime = new Date().getTime(); + let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; + console.info(TAG + " the Predicates_endWith average time is: " + averageTime + " μs"); + expect(averageTime < BASE_LINE).assertTrue(); + done(); + }) + + it('SUB_DDM_PERF_RDB_Predicates_isNull_001', 0, async function (done) { + let startTime = new Date().getTime(); + for (let i = 0; i < BASE_COUNT_FIRST; i++) { + let predicates = new dataRdb.RdbPredicates("test"); + for (let j = 0; j < BASE_COUNT_SECOND; j++) { + predicates.isNull("name"); + } + } + let endTime = new Date().getTime(); + let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; + console.info(TAG + " the Predicates_isNull average time is: " + averageTime + " μs"); + expect(averageTime < BASE_LINE).assertTrue(); + done(); + }) + + it('SUB_DDM_PERF_RDB_Predicates_isNotNull_001', 0, async function (done) { + let startTime = new Date().getTime(); + for (let i = 0; i < BASE_COUNT_FIRST; i++) { + let predicates = new dataRdb.RdbPredicates("test"); + for (let j = 0; j < BASE_COUNT_SECOND; j++) { + predicates.isNotNull("name"); + } + } + let endTime = new Date().getTime(); + let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; + console.info(TAG + " the Predicates_isNotNull average time is: " + averageTime + " μs"); + expect(averageTime < BASE_LINE).assertTrue(); + done(); + }) + + it('SUB_DDM_PERF_RDB_Predicates_like_001', 0, async function (done) { + let startTime = new Date().getTime(); + for (let i = 0; i < BASE_COUNT_FIRST; i++) { + let predicates = new dataRdb.RdbPredicates("test"); + for (let j = 0; j < BASE_COUNT_SECOND; j++) { + predicates.like("name", "li"); + } + } + let endTime = new Date().getTime(); + let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; + console.info(TAG + " the Predicates_like average time is: " + averageTime + " μs"); + expect(averageTime < BASE_LINE).assertTrue(); + done(); + }) + + it('SUB_DDM_PERF_RDB_Predicates_glob_001', 0, async function (done) { + let startTime = new Date().getTime(); + for (let i = 0; i < BASE_COUNT_FIRST; i++) { + let predicates = new dataRdb.RdbPredicates("test"); + for (let j = 0; j < BASE_COUNT_SECOND; j++) { + predicates.glob("name", "li"); + } + } + let endTime = new Date().getTime(); + let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; + console.info(TAG + " the Predicates_glob average time is: " + averageTime + " μs"); + expect(averageTime < BASE_LINE).assertTrue(); + done(); + }) + + it('SUB_DDM_PERF_RDB_Predicates_between_001', 0, async function (done) { + let startTime = new Date().getTime(); + for (let i = 0; i < BASE_COUNT_FIRST; i++) { + let predicates = new dataRdb.RdbPredicates("test"); + for (let j = 0; j < BASE_COUNT_SECOND; j++) { + predicates.between("age", 1, 100); + } + } + let endTime = new Date().getTime(); + let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; + console.info(TAG + " the Predicates_between average time is: " + averageTime + " μs"); + expect(averageTime < BASE_LINE).assertTrue(); + done(); + }) + + it('SUB_DDM_PERF_RDB_Predicates_notBetween_001', 0, async function (done) { + let startTime = new Date().getTime(); + for (let i = 0; i < BASE_COUNT_FIRST; i++) { + let predicates = new dataRdb.RdbPredicates("test"); + for (let j = 0; j < BASE_COUNT_SECOND; j++) { + predicates.notBetween("age", 1, 100); + } + } + let endTime = new Date().getTime(); + let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; + console.info(TAG + " the Predicates_notBetween average time is: " + averageTime + " μs"); + expect(averageTime < BASE_LINE).assertTrue(); + done(); + }) + + it('SUB_DDM_PERF_RDB_Predicates_greaterThan_001', 0, async function (done) { + let startTime = new Date().getTime(); + for (let i = 0; i < BASE_COUNT_FIRST; i++) { + let predicates = new dataRdb.RdbPredicates("test"); + for (let j = 0; j < BASE_COUNT_SECOND; j++) { + predicates.greaterThan("age", 1); + } + } + let endTime = new Date().getTime(); + let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; + console.info(TAG + " the Predicates_greaterThan average time is: " + averageTime + " μs"); + expect(averageTime < BASE_LINE).assertTrue(); + done(); + }) + + it('SUB_DDM_PERF_RDB_Predicates_lessThan_001', 0, async function (done) { + let startTime = new Date().getTime(); + for (let i = 0; i < BASE_COUNT_FIRST; i++) { + let predicates = new dataRdb.RdbPredicates("test"); + for (let j = 0; j < BASE_COUNT_SECOND; j++) { + predicates.lessThan("age", 1000); + } + } + let endTime = new Date().getTime(); + let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; + console.info(TAG + " the Predicates_lessThan average time is: " + averageTime + " μs"); + expect(averageTime < BASE_LINE).assertTrue(); + done(); + }) + + it('SUB_DDM_PERF_RDB_Predicates_greaterThanOrEqualTo_001', 0, async function (done) { + let startTime = new Date().getTime(); + for (let i = 0; i < BASE_COUNT_FIRST; i++) { + let predicates = new dataRdb.RdbPredicates("test"); + for (let j = 0; j < BASE_COUNT_SECOND; j++) { + predicates.greaterThanOrEqualTo("age", 1000); + } + } + let endTime = new Date().getTime(); + let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; + console.info(TAG + " the Predicates_greaterThanOrEqualTo average time is: " + averageTime + " μs"); + expect(averageTime < BASE_LINE).assertTrue(); + done(); + }) + + it('SUB_DDM_PERF_RDB_Predicates_lessThanOrEqualTo_001', 0, async function (done) { + let startTime = new Date().getTime(); + for (let i = 0; i < BASE_COUNT_FIRST; i++) { + let predicates = new dataRdb.RdbPredicates("test"); + for (let j = 0; j < BASE_COUNT_SECOND; j++) { + predicates.lessThanOrEqualTo("age", 1000); + } + } + let endTime = new Date().getTime(); + let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; + console.info(TAG + " the Predicates_lessThanOrEqualTo average time is: " + averageTime + " μs"); + expect(averageTime < BASE_LINE).assertTrue(); + done(); + }) + + it('SUB_DDM_PERF_RDB_Predicates_orderByAsc_001', 0, async function (done) { + let startTime = new Date().getTime(); + for (let i = 0; i < BASE_COUNT_FIRST; i++) { + let predicates = new dataRdb.RdbPredicates("test"); + for (let j = 0; j < BASE_COUNT_SECOND; j++) { + predicates.orderByAsc("name"); + } + } + let endTime = new Date().getTime(); + let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; + console.info(TAG + " the Predicates_orderByAsc average time is: " + averageTime + " μs"); + expect(averageTime < BASE_LINE).assertTrue(); + done(); + }) + + it('SUB_DDM_PERF_RDB_Predicates_orderByDesc_001', 0, async function (done) { + let startTime = new Date().getTime(); + for (let i = 0; i < BASE_COUNT_FIRST; i++) { + let predicates = new dataRdb.RdbPredicates("test"); + for (let j = 0; j < BASE_COUNT_SECOND; j++) { + predicates.orderByDesc("name"); + } + } + let endTime = new Date().getTime(); + let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; + console.info(TAG + " the Predicates_orderByDesc average time is: " + averageTime + " μs"); + expect(averageTime < BASE_LINE).assertTrue(); + done(); + }) + + it('SUB_DDM_PERF_RDB_Predicates_distinct_001', 0, async function (done) { + let startTime = new Date().getTime(); + for (let i = 0; i < BASE_COUNT_FIRST; i++) { + let predicates = new dataRdb.RdbPredicates("test"); + for (let j = 0; j < BASE_COUNT_SECOND; j++) { + predicates.distinct(); + } + } + let endTime = new Date().getTime(); + let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; + console.info(TAG + " the Predicates_distinct average time is: " + averageTime + " μs"); + expect(averageTime < BASE_LINE).assertTrue(); + done(); + }) + + it('SUB_DDM_PERF_RDB_Predicates_limitAs_001', 0, async function (done) { + let startTime = new Date().getTime(); + for (let i = 0; i < BASE_COUNT; i++) { + let predicates = new dataRdb.RdbPredicates("test"); + predicates.limitAs(6); + } + let endTime = new Date().getTime(); + let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; + console.info(TAG + " the Predicates_limitAs average time is: " + averageTime + " μs"); + expect(averageTime < BASE_LINE).assertTrue(); + done(); + }) + + it('SUB_DDM_PERF_RDB_Predicates_offsetAs_001', 0, async function (done) { + let startTime = new Date().getTime(); + for (let i = 0; i < BASE_COUNT; i++) { + let predicates = new dataRdb.RdbPredicates("test"); + predicates.offsetAs(6); + } + let endTime = new Date().getTime(); + let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; + console.info(TAG + " the Predicates_offsetAs average time is: " + averageTime + " μs"); + expect(averageTime < BASE_LINE).assertTrue(); + done(); + }) + + it('SUB_DDM_PERF_RDB_Predicates_groupBy_001', 0, async function (done) { + let nameArr = new Array(); + nameArr.push("id"); + nameArr.push("name"); + let startTime = new Date().getTime(); + for (let i = 0; i < BASE_COUNT_FIRST; i++) { + let predicates = new dataRdb.RdbPredicates("test"); + for (let j = 0; j < BASE_COUNT_SECOND; j++) { + predicates.groupBy(nameArr); + } + } + let endTime = new Date().getTime(); + let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; + console.info(TAG + " the Predicates_groupBy average time is: " + averageTime + " μs"); + expect(averageTime < BASE_LINE).assertTrue(); + done(); + }) + + it('SUB_DDM_PERF_RDB_Predicates_indexedBy_001', 0, async function (done) { + let startTime = new Date().getTime(); + for (let i = 0; i < BASE_COUNT_FIRST; i++) { + let predicates = new dataRdb.RdbPredicates("test"); + for (let j = 0; j < BASE_COUNT_SECOND; j++) { + predicates.indexedBy("name"); + } + } + let endTime = new Date().getTime(); + let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; + console.info(TAG + " the Predicates_indexedBy average time is: " + averageTime + " μs"); + expect(averageTime < BASE_LINE).assertTrue(); + done(); + }) + + it('SUB_DDM_PERF_RDB_Predicates_in_001', 0, async function (done) { + let nameArr = new Array(); + nameArr.push("id"); + nameArr.push("name"); + let startTime = new Date().getTime(); + for (let i = 0; i < BASE_COUNT_FIRST; i++) { + let predicates = new dataRdb.RdbPredicates("test"); + for (let j = 0; j < BASE_COUNT_SECOND; j++) { + predicates.in("name", nameArr); + } + } + let endTime = new Date().getTime(); + let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; + console.info(TAG + " the Predicates_in average time is: " + averageTime + " μs"); + expect(averageTime < BASE_LINE).assertTrue(); + done(); + }) + + it('SUB_DDM_PERF_RDB_Predicates_notIn(_001', 0, async function (done) { + let nameArr = new Array(); + nameArr.push("zhangsan"); + nameArr.push("lisi"); + let startTime = new Date().getTime(); + for (let i = 0; i < BASE_COUNT_FIRST; i++) { + let predicates = new dataRdb.RdbPredicates("test"); + for (let j = 0; j < BASE_COUNT_SECOND; j++) { + predicates.notIn("name", nameArr); + } + } + let endTime = new Date().getTime(); + let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; + console.info(TAG + " the Predicates_notIn average time is: " + averageTime + " μs"); + expect(averageTime < BASE_LINE).assertTrue(); + done(); + }) + + console.info(TAG + "*************Unit Test End*************") }) \ No newline at end of file diff --git a/relational_store/test/js/relationalstore/performance/src/RdbHelperCallbackPerf.js b/relational_store/test/js/relationalstore/performance/src/RdbHelperCallbackPerf.js index ffb0ce80..7781c9dd 100644 --- a/relational_store/test/js/relationalstore/performance/src/RdbHelperCallbackPerf.js +++ b/relational_store/test/js/relationalstore/performance/src/RdbHelperCallbackPerf.js @@ -13,18 +13,16 @@ * limitations under the License. */ -import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect, Assert } from 'deccjsunit/index'; -import dataRdb from '@ohos.data.rdb'; +import {describe, beforeAll, beforeEach, afterEach, afterAll, it, expect, Assert} from 'deccjsunit/index'; +import dataRdb from '@ohos.data.relationalStore'; import featureAbility from '@ohos.ability.featureAbility'; import deviceInfo from '@ohos.deviceInfo'; const TAG = "[RDBHELPER_CALLBACK]"; -const CREATE_TABLE_TEST = "CREATE TABLE IF NOT EXISTS test (id INTEGER PRIMARY KEY AUTOINCREMENT, " -+ "name TEXT, age INTEGER, salary REAL, blobType BLOB)"; - const DB_NAME = "rdbCallback.db"; const STORE_CONFIG = { - name: DB_NAME, + name: DB_NAME, + securityLevel: dataRdb.SecurityLevel.S1 } let context = featureAbility.getContext(); var rdbStore = undefined; @@ -34,62 +32,62 @@ const BASE_LINE_PHONE = 3000; // callback phone base line const BASE_LINE = (deviceInfo.deviceType == "tablet") ? BASE_LINE_TABLE : BASE_LINE_PHONE; describe('rdbHelperCallbackPerf', function () { - beforeAll(async function () { - console.info(TAG + 'beforeAll'); - }) - beforeEach(async function () { - console.info(TAG + 'beforeEach'); - }) - afterEach(async function () { - console.info(TAG + 'afterEach'); - }) - afterAll(async function () { - console.info(TAG + 'afterAll'); - rdbStore = null - await dataRdb.deleteRdbStore(context, DB_NAME); - }) + beforeAll(async function () { + console.info(TAG + 'beforeAll'); + }) + beforeEach(async function () { + console.info(TAG + 'beforeEach'); + }) + afterEach(async function () { + console.info(TAG + 'afterEach'); + }) + afterAll(async function () { + console.info(TAG + 'afterAll'); + rdbStore = null + await dataRdb.deleteRdbStore(context, DB_NAME); + }) - console.log(TAG + "*************Unit Test Begin*************"); + console.log(TAG + "*************Unit Test Begin*************"); - it('SUB_DDM_PERF_RDB_getRdbStore_Callback_001', 0, async function (done) { - let averageTime = 0; + it('SUB_DDM_PERF_RDB_getRdbStore_Callback_001', 0, async function (done) { + let averageTime = 0; - async function getRdbStoreCallBackPerf(index) { - dataRdb.getRdbStore(context, STORE_CONFIG, 1, function (err, rdbStore) { - if (index < BASE_COUNT) { - getRdbStoreCallBackPerf(index + 1); - } else { - let endTime = new Date().getTime(); - averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; - console.info(TAG + " the getRdbStore_Callback average time is: " + averageTime + " μs"); - expect(averageTime < BASE_LINE).assertTrue(); - done(); - } - }) + async function getRdbStoreCallBackPerf(index) { + dataRdb.getRdbStore(context, STORE_CONFIG, function (err, rdbStore) { + if (index < BASE_COUNT) { + getRdbStoreCallBackPerf(index + 1); + } else { + let endTime = new Date().getTime(); + averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; + console.info(TAG + " the getRdbStore_Callback average time is: " + averageTime + " μs"); + expect(averageTime < BASE_LINE).assertTrue(); + done(); } + }) + } - let startTime = new Date().getTime(); - await getRdbStoreCallBackPerf(0); - }) + let startTime = new Date().getTime(); + await getRdbStoreCallBackPerf(0); + }) - it('SUB_DDM_PERF_RDB_deleteRdbStore_Callback_001', 0, async function (done) { - let averageTime = 0; + it('SUB_DDM_PERF_RDB_deleteRdbStore_Callback_001', 0, async function (done) { + let averageTime = 0; - async function deleteRdbStoreCallBackPerf(index) { - dataRdb.deleteRdbStore(context, DB_NAME, function (err, data) { - if (index < BASE_COUNT) { - deleteRdbStoreCallBackPerf(index + 1); - } else { - let endTime = new Date().getTime(); - averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; - console.info(TAG + " the deleteRdbStore_Callback average time is: " + averageTime + " μs"); - expect(averageTime < BASE_LINE).assertTrue(); - done(); - } - }) + async function deleteRdbStoreCallBackPerf(index) { + dataRdb.deleteRdbStore(context, DB_NAME, function (err, data) { + if (index < BASE_COUNT) { + deleteRdbStoreCallBackPerf(index + 1); + } else { + let endTime = new Date().getTime(); + averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; + console.info(TAG + " the deleteRdbStore_Callback average time is: " + averageTime + " μs"); + expect(averageTime < BASE_LINE).assertTrue(); + done(); } + }) + } - let startTime = new Date().getTime(); - await deleteRdbStoreCallBackPerf(0); - }) + let startTime = new Date().getTime(); + await deleteRdbStoreCallBackPerf(0); + }) }) \ No newline at end of file diff --git a/relational_store/test/js/relationalstore/performance/src/RdbHelperPromisePerf.js b/relational_store/test/js/relationalstore/performance/src/RdbHelperPromisePerf.js index fad1e09e..d507666d 100644 --- a/relational_store/test/js/relationalstore/performance/src/RdbHelperPromisePerf.js +++ b/relational_store/test/js/relationalstore/performance/src/RdbHelperPromisePerf.js @@ -13,18 +13,16 @@ * limitations under the License. */ -import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect, Assert } from 'deccjsunit/index'; -import dataRdb from '@ohos.data.rdb'; +import {describe, beforeAll, beforeEach, afterEach, afterAll, it, expect, Assert} from 'deccjsunit/index'; +import dataRdb from '@ohos.data.relationalStore'; import featureAbility from '@ohos.ability.featureAbility'; import deviceInfo from '@ohos.deviceInfo'; const TAG = "[RDBHELPER_PROMISE]"; -const CREATE_TABLE_TEST = "CREATE TABLE IF NOT EXISTS test (id INTEGER PRIMARY KEY AUTOINCREMENT, " -+ "name TEXT, age INTEGER, salary REAL, blobType BLOB)"; - const DB_NAME = "rdbPromise.db"; const STORE_CONFIG = { - name: DB_NAME, + name: DB_NAME, + securityLevel: dataRdb.SecurityLevel.S1 } let context = featureAbility.getContext(); var rdbStore = undefined; @@ -34,47 +32,47 @@ const BASE_LINE_PHONE = 3000; // callback phone base line const BASE_LINE = (deviceInfo.deviceType == "tablet") ? BASE_LINE_TABLE : BASE_LINE_PHONE; describe('rdbHelperPromisePerf', function () { - beforeAll(async function () { - console.info(TAG + 'beforeAll'); - }) - beforeEach(async function () { - console.info(TAG + 'beforeEach'); - }) - afterEach(async function () { - console.info(TAG + 'afterEach'); - }) - afterAll(async function () { - console.info(TAG + 'afterAll'); - rdbStore = null; - await dataRdb.deleteRdbStore(context, DB_NAME); - }) + beforeAll(async function () { + console.info(TAG + 'beforeAll'); + }) + beforeEach(async function () { + console.info(TAG + 'beforeEach'); + }) + afterEach(async function () { + console.info(TAG + 'afterEach'); + }) + afterAll(async function () { + console.info(TAG + 'afterAll'); + rdbStore = null; + await dataRdb.deleteRdbStore(context, DB_NAME); + }) - console.log(TAG + "*************Unit Test Begin*************"); + console.log(TAG + "*************Unit Test Begin*************"); - it('SUB_DDM_PERF_RDB_getRdbStore_Promise_001', 0, async function (done) { - let averageTime = 0; - let startTime = new Date().getTime(); - for (var i = 0; i < BASE_COUNT; i++) { - await dataRdb.getRdbStore(context, STORE_CONFIG, 1); - } - let endTime = new Date().getTime(); - averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; - console.info(TAG + " the getRdbStore_Promise average time is: " + averageTime + " μs"); - expect(averageTime < BASE_LINE).assertTrue(); - done(); - }) + it('SUB_DDM_PERF_RDB_getRdbStore_Promise_001', 0, async function (done) { + let averageTime = 0; + let startTime = new Date().getTime(); + for (var i = 0; i < BASE_COUNT; i++) { + await dataRdb.getRdbStore(context, STORE_CONFIG); + } + let endTime = new Date().getTime(); + averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; + console.info(TAG + " the getRdbStore_Promise average time is: " + averageTime + " μs"); + expect(averageTime < BASE_LINE).assertTrue(); + done(); + }) - it('SUB_DDM_PERF_RDB_deleteRdbStore_Promise_001', 0, async function (done) { - let averageTime = 0; - let startTime = new Date().getTime(); - for (var i = 0; i < BASE_COUNT; i++) { - await dataRdb.deleteRdbStore(context, DB_NAME, 1); - } - let endTime = new Date().getTime(); - averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; - console.info(TAG + " the deleteRdbStore_Promise average time is: " + averageTime + " μs"); - expect(averageTime < BASE_LINE).assertTrue(); - done(); - console.info(TAG + "*************Unit Test End*************") - }) + it('SUB_DDM_PERF_RDB_deleteRdbStore_Promise_001', 0, async function (done) { + let averageTime = 0; + let startTime = new Date().getTime(); + for (var i = 0; i < BASE_COUNT; i++) { + await dataRdb.deleteRdbStore(context, DB_NAME, 1); + } + let endTime = new Date().getTime(); + averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; + console.info(TAG + " the deleteRdbStore_Promise average time is: " + averageTime + " μs"); + expect(averageTime < BASE_LINE).assertTrue(); + done(); + console.info(TAG + "*************Unit Test End*************") + }) }) \ No newline at end of file diff --git a/relational_store/test/js/relationalstore/performance/src/RdbStoreCallbackPerf.js b/relational_store/test/js/relationalstore/performance/src/RdbStoreCallbackPerf.js index 0c4fc81f..72aed689 100644 --- a/relational_store/test/js/relationalstore/performance/src/RdbStoreCallbackPerf.js +++ b/relational_store/test/js/relationalstore/performance/src/RdbStoreCallbackPerf.js @@ -13,18 +13,19 @@ * limitations under the License. */ -import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect, Assert } from 'deccjsunit/index'; -import dataRdb from '@ohos.data.rdb'; +import {describe, beforeAll, beforeEach, afterEach, afterAll, it, expect, Assert} from 'deccjsunit/index'; +import dataRdb from '@ohos.data.relationalStore'; import featureAbility from '@ohos.ability.featureAbility'; import deviceInfo from '@ohos.deviceInfo'; const TAG = "[RDBSTORE_CALLBACK]"; const CREATE_TABLE_TEST = "CREATE TABLE IF NOT EXISTS test (id INTEGER PRIMARY KEY AUTOINCREMENT, " -+ "name TEXT, age INTEGER, salary REAL, blobType BLOB)"; + + "name TEXT, age INTEGER, salary REAL, blobType BLOB)"; const DB_NAME = "rdbStoreCallback.db"; const STORE_CONFIG = { - name: DB_NAME, + name: DB_NAME, + securityLevel: dataRdb.SecurityLevel.S1 } let context = featureAbility.getContext(); var rdbStore = undefined; @@ -35,91 +36,91 @@ const BASE_LINE_PHONE = 7000; // callback phone base line const BASE_LINE = (deviceInfo.deviceType == "tablet") ? BASE_LINE_TABLE : BASE_LINE_PHONE; describe('rdbStoreCallbackPerf', function () { - beforeAll(async function () { - console.info(TAG + 'beforeAll'); - rdbStore = await dataRdb.getRdbStore(context, STORE_CONFIG, 1); - }) - beforeEach(async function () { - console.info(TAG + 'beforeEach'); - await rdbStore.executeSql(CREATE_TABLE_TEST, null); - await prepareTestData(); - }) - afterEach(async function () { - console.info(TAG + 'afterEach'); - await rdbStore.executeSql("drop table test"); - }) - afterAll(async function () { - console.info(TAG + 'afterAll'); - rdbStore = null; - await dataRdb.deleteRdbStore(context, DB_NAME); - }) + beforeAll(async function () { + console.info(TAG + 'beforeAll'); + rdbStore = await dataRdb.getRdbStore(context, STORE_CONFIG); + }) + beforeEach(async function () { + console.info(TAG + 'beforeEach'); + await rdbStore.executeSql(CREATE_TABLE_TEST, null); + await prepareTestData(); + }) + afterEach(async function () { + console.info(TAG + 'afterEach'); + await rdbStore.executeSql("drop table test"); + }) + afterAll(async function () { + console.info(TAG + 'afterAll'); + rdbStore = null; + await dataRdb.deleteRdbStore(context, DB_NAME); + }) - async function prepareTestData() { - console.info(TAG + "prepare for query performance test"); - var u8 = new Uint8Array([1, 2, 3]); - var valueBucket = { - "name": "zhangsan", - "age": 18, - "salary": 100.5, - "blobType": u8, - } - await rdbStore.insert("test", valueBucket); + async function prepareTestData() { + console.info(TAG + "prepare for query performance test"); + var u8 = new Uint8Array([1, 2, 3]); + var valueBucket = { + "name": "zhangsan", + "age": 18, + "salary": 100.5, + "blobType": u8, } + await rdbStore.insert("test", valueBucket); + } - console.log(TAG + "*************Unit Test Begin*************"); + console.log(TAG + "*************Unit Test Begin*************"); - it('SUB_DDM_PERF_RDB_query_Callback_001', 0, async function (done) { - let averageTime = 0; - let predicates = new dataRdb.RdbPredicates("test"); - predicates.equalTo("age", 10); + it('SUB_DDM_PERF_RDB_query_Callback_001', 0, async function (done) { + let averageTime = 0; + let predicates = new dataRdb.RdbPredicates("test"); + predicates.equalTo("age", 10); - async function queryCallbackPerf(index) { - rdbStore.query(predicates, [], function (err, resultSet) { - resultSet.close(); - if (index < BASE_COUNT) { - queryCallbackPerf(index + 1); - } else { - let endTime = new Date().getTime(); - averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; - console.info(TAG + " the query_Callback average time is: " + averageTime + " μs"); - expect(averageTime < BASE_LINE).assertTrue(); - console.info(TAG + "*************Unit Test End*************"); - done(); - } - }) + async function queryCallbackPerf(index) { + rdbStore.query(predicates, [], function (err, resultSet) { + resultSet.close(); + if (index < BASE_COUNT) { + queryCallbackPerf(index + 1); + } else { + let endTime = new Date().getTime(); + averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; + console.info(TAG + " the query_Callback average time is: " + averageTime + " μs"); + expect(averageTime < BASE_LINE).assertTrue(); + console.info(TAG + "*************Unit Test End*************"); + done(); } + }) + } - let startTime = new Date().getTime(); - queryCallbackPerf(0); - }) + let startTime = new Date().getTime(); + queryCallbackPerf(0); + }) - it('SUB_DDM_PERF_RDB_insert_Callback_001', 0, async function (done) { - let averageTime = 0; - var uBlob = new Uint8Array([1, 2, 3]); - var insertValueBucket = { - "name": "zhangsan", - "age": 18, - "salary": 100.5, - "blobType": uBlob, - } - let predicates = new dataRdb.RdbPredicates("test"); - predicates.equalTo("age", 10); + it('SUB_DDM_PERF_RDB_insert_Callback_001', 0, async function (done) { + let averageTime = 0; + var uBlob = new Uint8Array([1, 2, 3]); + var insertValueBucket = { + "name": "zhangsan", + "age": 18, + "salary": 100.5, + "blobType": uBlob, + } + let predicates = new dataRdb.RdbPredicates("test"); + predicates.equalTo("age", 10); - async function InsertCallbackPerf(index) { - rdbStore.insert("test", insertValueBucket, function (err, data) { - if (index < INSERT_BASE_COUNT) { - InsertCallbackPerf(index + 1); - } else { - let endTime = new Date().getTime(); - averageTime = ((endTime - startTime) * 1000) / INSERT_BASE_COUNT; - console.info(TAG + " the insert_Callback average time is: " + averageTime + " μs"); - expect(averageTime < BASE_LINE).assertTrue(); - done(); - } - }) + async function InsertCallbackPerf(index) { + rdbStore.insert("test", insertValueBucket, function (err, data) { + if (index < INSERT_BASE_COUNT) { + InsertCallbackPerf(index + 1); + } else { + let endTime = new Date().getTime(); + averageTime = ((endTime - startTime) * 1000) / INSERT_BASE_COUNT; + console.info(TAG + " the insert_Callback average time is: " + averageTime + " μs"); + expect(averageTime < BASE_LINE).assertTrue(); + done(); } + }) + } - let startTime = new Date().getTime(); - InsertCallbackPerf(0); - }) + let startTime = new Date().getTime(); + InsertCallbackPerf(0); + }) }) \ No newline at end of file diff --git a/relational_store/test/js/relationalstore/performance/src/RdbStoreOthersCallbackPerf.js b/relational_store/test/js/relationalstore/performance/src/RdbStoreOthersCallbackPerf.js index 77e7cb07..1bce013b 100644 --- a/relational_store/test/js/relationalstore/performance/src/RdbStoreOthersCallbackPerf.js +++ b/relational_store/test/js/relationalstore/performance/src/RdbStoreOthersCallbackPerf.js @@ -13,18 +13,19 @@ * limitations under the License. */ -import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect, Assert } from 'deccjsunit/index'; -import dataRdb from '@ohos.data.rdb'; +import {describe, beforeAll, beforeEach, afterEach, afterAll, it, expect, Assert} from 'deccjsunit/index'; +import dataRdb from '@ohos.data.relationalStore'; import featureAbility from '@ohos.ability.featureAbility'; import deviceInfo from '@ohos.deviceInfo'; const TAG = "[RDBSTORE_OTHERS_CALLBACK]"; const CREATE_TABLE_TEST = "CREATE TABLE IF NOT EXISTS test (id INTEGER PRIMARY KEY AUTOINCREMENT, " -+ "name TEXT, age INTEGER, salary REAL, blobType BLOB)"; + + "name TEXT, age INTEGER, salary REAL, blobType BLOB)"; const DB_NAME = "rdbUpdateCallback.db"; const STORE_CONFIG = { - name: DB_NAME, + name: DB_NAME, + securityLevel: dataRdb.SecurityLevel.S1 } let context = featureAbility.getContext(); var rdbStore = undefined; @@ -35,131 +36,131 @@ const BASE_LINE_PHONE = 15000; // callback phone base line const BASE_LINE = (deviceInfo.deviceType == "tablet") ? BASE_LINE_TABLE : BASE_LINE_PHONE; describe('rdbStoreOthersCallbackPerf', function () { - beforeAll(async function () { - console.info(TAG + 'beforeAll'); - rdbStore = await dataRdb.getRdbStore(context, STORE_CONFIG, 1); - }) - beforeEach(async function () { - console.info(TAG + 'beforeEach'); - await rdbStore.executeSql(CREATE_TABLE_TEST, null); - await prepareTestData(); - }) - afterEach(async function () { - console.info(TAG + 'afterEach'); - await rdbStore.executeSql("drop table test"); - }) - afterAll(async function () { - console.info(TAG + 'afterAll'); - rdbStore = null; - await dataRdb.deleteRdbStore(context, DB_NAME); - }) - - async function prepareTestData() { - console.info(TAG + "prepare for query performance test"); - var u8 = new Uint8Array([1, 2, 3]); - var valueBucket = { - "name": "zhangsan", - "age": 18, - "salary": 100.5, - "blobType": u8, - } - await rdbStore.insert("test", valueBucket); + beforeAll(async function () { + console.info(TAG + 'beforeAll'); + rdbStore = await dataRdb.getRdbStore(context, STORE_CONFIG); + }) + beforeEach(async function () { + console.info(TAG + 'beforeEach'); + await rdbStore.executeSql(CREATE_TABLE_TEST, null); + await prepareTestData(); + }) + afterEach(async function () { + console.info(TAG + 'afterEach'); + await rdbStore.executeSql("drop table test"); + }) + afterAll(async function () { + console.info(TAG + 'afterAll'); + rdbStore = null; + await dataRdb.deleteRdbStore(context, DB_NAME); + }) + + async function prepareTestData() { + console.info(TAG + "prepare for query performance test"); + var u8 = new Uint8Array([1, 2, 3]); + var valueBucket = { + "name": "zhangsan", + "age": 18, + "salary": 100.5, + "blobType": u8, } - - console.log(TAG + "*************Unit Test Begin*************"); - - it('SUB_DDM_PERF_RDB_update_Callback_001', 0, async function (done) { - let averageTime = 0; - var uBlob = new Uint8Array([1, 2, 3]) - var updateVB = { - "name": "zhangsan", - "age": 18, - "salary": 100.5, - "blobType": uBlob, - } - let predicates = new dataRdb.RdbPredicates("test"); - - async function updateCallbackPerf(index) { - predicates.equalTo("age", 18); - rdbStore.update(updateVB, predicates, function (err, data) { - if (index < SPECIAL_BASE_COUNT) { - updateCallbackPerf(index + 1); - } else { - let endTime = new Date().getTime(); - averageTime = ((endTime - startTime) * 1000) / SPECIAL_BASE_COUNT; - console.info(TAG + " the update_Callback average time is: " + averageTime + " μs"); - expect(averageTime < BASE_LINE).assertTrue(); - done(); - } - }) + await rdbStore.insert("test", valueBucket); + } + + console.log(TAG + "*************Unit Test Begin*************"); + + it('SUB_DDM_PERF_RDB_update_Callback_001', 0, async function (done) { + let averageTime = 0; + var uBlob = new Uint8Array([1, 2, 3]) + var updateVB = { + "name": "zhangsan", + "age": 18, + "salary": 100.5, + "blobType": uBlob, + } + let predicates = new dataRdb.RdbPredicates("test"); + + async function updateCallbackPerf(index) { + predicates.equalTo("age", 18); + rdbStore.update(updateVB, predicates, function (err, data) { + if (index < SPECIAL_BASE_COUNT) { + updateCallbackPerf(index + 1); + } else { + let endTime = new Date().getTime(); + averageTime = ((endTime - startTime) * 1000) / SPECIAL_BASE_COUNT; + console.info(TAG + " the update_Callback average time is: " + averageTime + " μs"); + expect(averageTime < BASE_LINE).assertTrue(); + done(); } + }) + } - let startTime = new Date().getTime(); - updateCallbackPerf(0); - }) - - it('SUB_DDM_PERF_RDB_delete_Callback_001', 0, async function (done) { - let averageTime = 0; - let predicates = new dataRdb.RdbPredicates("test"); - predicates.equalTo("age", 0); - - async function deleteCallbackPerf(index) { - rdbStore.delete(predicates, function (err, data) { - if (index < BASE_COUNT) { - deleteCallbackPerf(index + 1) - } else { - let endTime = new Date().getTime(); - averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; - console.info(TAG + " the delete_Callback average time is: " + averageTime + " μs"); - expect(averageTime < BASE_LINE).assertTrue(); - done(); - } - }) + let startTime = new Date().getTime(); + updateCallbackPerf(0); + }) + + it('SUB_DDM_PERF_RDB_delete_Callback_001', 0, async function (done) { + let averageTime = 0; + let predicates = new dataRdb.RdbPredicates("test"); + predicates.equalTo("age", 0); + + async function deleteCallbackPerf(index) { + rdbStore.delete(predicates, function (err, data) { + if (index < BASE_COUNT) { + deleteCallbackPerf(index + 1) + } else { + let endTime = new Date().getTime(); + averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; + console.info(TAG + " the delete_Callback average time is: " + averageTime + " μs"); + expect(averageTime < BASE_LINE).assertTrue(); + done(); } + }) + } - let startTime = new Date().getTime(); - deleteCallbackPerf(0); - }) - - it('SUB_DDM_PERF_RDB_querySql_Callback_001', 0, async function (done) { - let averageTime = 0; - - async function querySqlCallbackPerf(index) { - rdbStore.querySql("select * from test", [], function (err, data) { - if (index < BASE_COUNT) { - querySqlCallbackPerf(index + 1); - } else { - let endTime = new Date().getTime(); - averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; - console.info(TAG + " the querySql_Callback average time is: " + averageTime + " μs"); - expect(averageTime < BASE_LINE).assertTrue(); - done(); - } - }) + let startTime = new Date().getTime(); + deleteCallbackPerf(0); + }) + + it('SUB_DDM_PERF_RDB_querySql_Callback_001', 0, async function (done) { + let averageTime = 0; + + async function querySqlCallbackPerf(index) { + rdbStore.querySql("select * from test", [], function (err, data) { + if (index < BASE_COUNT) { + querySqlCallbackPerf(index + 1); + } else { + let endTime = new Date().getTime(); + averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; + console.info(TAG + " the querySql_Callback average time is: " + averageTime + " μs"); + expect(averageTime < BASE_LINE).assertTrue(); + done(); } + }) + } - let startTime = new Date().getTime(); - querySqlCallbackPerf(0); - }) - - it('SUB_DDM_PERF_RDB_executeSql_Callback_001', 0, async function (done) { - let averageTime = 0; - - async function executeSqlCallbackPerf(index) { - rdbStore.executeSql("insert into test (name, age) values ('tom', 22)", function (err, data) { - if (index < SPECIAL_BASE_COUNT) { - executeSqlCallbackPerf(index + 1); - } else { - let endTime = new Date().getTime(); - averageTime = ((endTime - startTime) * 1000) / SPECIAL_BASE_COUNT; - console.info(TAG + " the executeSql_Callback average time is: " + averageTime + " μs"); - expect(averageTime < BASE_LINE).assertTrue(); - done(); - } - }) + let startTime = new Date().getTime(); + querySqlCallbackPerf(0); + }) + + it('SUB_DDM_PERF_RDB_executeSql_Callback_001', 0, async function (done) { + let averageTime = 0; + + async function executeSqlCallbackPerf(index) { + rdbStore.executeSql("insert into test (name, age) values ('tom', 22)", function (err, data) { + if (index < SPECIAL_BASE_COUNT) { + executeSqlCallbackPerf(index + 1); + } else { + let endTime = new Date().getTime(); + averageTime = ((endTime - startTime) * 1000) / SPECIAL_BASE_COUNT; + console.info(TAG + " the executeSql_Callback average time is: " + averageTime + " μs"); + expect(averageTime < BASE_LINE).assertTrue(); + done(); } + }) + } - let startTime = new Date().getTime(); - executeSqlCallbackPerf(0); - }) + let startTime = new Date().getTime(); + executeSqlCallbackPerf(0); + }) }) diff --git a/relational_store/test/js/relationalstore/performance/src/RdbStorePromisePerf.js b/relational_store/test/js/relationalstore/performance/src/RdbStorePromisePerf.js index 87c157e0..a2209b6f 100644 --- a/relational_store/test/js/relationalstore/performance/src/RdbStorePromisePerf.js +++ b/relational_store/test/js/relationalstore/performance/src/RdbStorePromisePerf.js @@ -13,18 +13,19 @@ * limitations under the License. */ -import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect, Assert } from 'deccjsunit/index'; -import dataRdb from '@ohos.data.rdb'; +import {describe, beforeAll, beforeEach, afterEach, afterAll, it, expect, Assert} from 'deccjsunit/index'; +import dataRdb from '@ohos.data.relationalStore'; import featureAbility from '@ohos.ability.featureAbility'; import deviceInfo from '@ohos.deviceInfo'; const TAG = "[RDBSTORE_PROMISE]"; const CREATE_TABLE_TEST = "CREATE TABLE IF NOT EXISTS test (id INTEGER PRIMARY KEY AUTOINCREMENT, " -+ "name TEXT, age INTEGER, salary REAL, blobType BLOB)"; + + "name TEXT, age INTEGER, salary REAL, blobType BLOB)"; const DB_NAME = "rdbStorePromise.db"; const STORE_CONFIG = { - name: DB_NAME, + name: DB_NAME, + securityLevel: dataRdb.SecurityLevel.S1 } let context = featureAbility.getContext(); var rdbStore = undefined; @@ -34,53 +35,53 @@ const BASE_LINE_PHONE = 3000; // callback phone base line const BASE_LINE = (deviceInfo.deviceType == "tablet") ? BASE_LINE_TABLE : BASE_LINE_PHONE; describe('rdbStorePromisePerf', function () { - beforeAll(async function () { - console.info(TAG + 'beforeAll'); - rdbStore = await dataRdb.getRdbStore(context, STORE_CONFIG, 1); - }) - beforeEach(async function () { - console.info(TAG + 'beforeEach'); - await rdbStore.executeSql(CREATE_TABLE_TEST, null); - await prepareTestData(); - }) - afterEach(async function () { - console.info(TAG + 'afterEach'); - await rdbStore.executeSql("drop table test"); - }) - afterAll(async function () { - console.info(TAG + 'afterAll'); - rdbStore = null; - await dataRdb.deleteRdbStore(context, DB_NAME); - }) + beforeAll(async function () { + console.info(TAG + 'beforeAll'); + rdbStore = await dataRdb.getRdbStore(context, STORE_CONFIG); + }) + beforeEach(async function () { + console.info(TAG + 'beforeEach'); + await rdbStore.executeSql(CREATE_TABLE_TEST, null); + await prepareTestData(); + }) + afterEach(async function () { + console.info(TAG + 'afterEach'); + await rdbStore.executeSql("drop table test"); + }) + afterAll(async function () { + console.info(TAG + 'afterAll'); + rdbStore = null; + await dataRdb.deleteRdbStore(context, DB_NAME); + }) - async function prepareTestData() { - console.info(TAG + "prepare for query performance test") - var u8 = new Uint8Array([1, 2, 3]) - var valueBucket = { - "name": "zhangsan", - "age": 18, - "salary": 100.5, - "blobType": u8, - } - await dataRdb.insert("test", valueBucket); + async function prepareTestData() { + console.info(TAG + "prepare for query performance test") + var u8 = new Uint8Array([1, 2, 3]) + var valueBucket = { + "name": "zhangsan", + "age": 18, + "salary": 100.5, + "blobType": u8, } + await dataRdb.insert("test", valueBucket); + } - console.log(TAG + "*************Unit Test Begin*************"); + console.log(TAG + "*************Unit Test Begin*************"); - it('SUB_DDM_PERF_RDB_query_Promise_001', 0, async function (done) { - let averageTime = 0; - let predicates = new dataRdb.RdbPredicates("test"); - predicates.equalTo("age", 10); - let startTime = new Date().getTime(); - for (var i = 0; i < BASE_COUNT; i++) { - let resultSet = await rdbStore.query(predicates, []); - resultSet.close(); - } - let endTime = new Date().getTime(); - averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; - console.info(TAG + " the query_Promise average time is: " + averageTime + " μs"); - expect(averageTime < BASE_LINE).assertTrue(); - console.info(TAG + "*************Unit Test End*************"); - done(); - }) + it('SUB_DDM_PERF_RDB_query_Promise_001', 0, async function (done) { + let averageTime = 0; + let predicates = new dataRdb.RdbPredicates("test"); + predicates.equalTo("age", 10); + let startTime = new Date().getTime(); + for (var i = 0; i < BASE_COUNT; i++) { + let resultSet = await rdbStore.query(predicates, []); + resultSet.close(); + } + let endTime = new Date().getTime(); + averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; + console.info(TAG + " the query_Promise average time is: " + averageTime + " μs"); + expect(averageTime < BASE_LINE).assertTrue(); + console.info(TAG + "*************Unit Test End*************"); + done(); + }) }) diff --git a/relational_store/test/js/relationalstore/performance/src/RdbStoreSyncPerf.js b/relational_store/test/js/relationalstore/performance/src/RdbStoreSyncPerf.js index b8b922b9..3a3b90f2 100644 --- a/relational_store/test/js/relationalstore/performance/src/RdbStoreSyncPerf.js +++ b/relational_store/test/js/relationalstore/performance/src/RdbStoreSyncPerf.js @@ -13,18 +13,16 @@ * limitations under the License. */ -import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect, Assert } from 'deccjsunit/index'; -import dataRdb from '@ohos.data.rdb'; +import {describe, beforeAll, beforeEach, afterEach, afterAll, it, expect, Assert} from 'deccjsunit/index'; +import dataRdb from '@ohos.data.relationalStore'; import featureAbility from '@ohos.ability.featureAbility'; import deviceInfo from '@ohos.deviceInfo'; const TAG = "[RDB_SYNC_PROMISE]"; -const CREATE_TABLE_TEST = "CREATE TABLE IF NOT EXISTS test (id INTEGER PRIMARY KEY AUTOINCREMENT, " -+ "name TEXT, age INTEGER, salary REAL, blobType BLOB)"; - const DB_NAME = "rdbSync.db"; const STORE_CONFIG = { - name: DB_NAME, + name: DB_NAME, + securityLevel: dataRdb.SecurityLevel.S1 } let context = featureAbility.getContext(); var rdbStore = undefined; @@ -35,64 +33,64 @@ const BASE_LINE = (deviceInfo.deviceType == "tablet") ? BASE_LINE_TABLE : BASE_L describe('rdbStoreSyncPerf', function () { - beforeAll(async function () { - console.info(TAG + 'beforeAll'); - rdbStore = await dataRdb.getRdbStore(context, STORE_CONFIG, 1); - }) - beforeEach(async function () { - console.info(TAG + 'beforeEach'); - }) - afterEach(async function () { - console.info(TAG + 'afterEach'); - }) - afterAll(async function () { - console.info(TAG + 'afterAll'); - rdbStore = null - await dataRdb.deleteRdbStore(context, DB_NAME); - }) + beforeAll(async function () { + console.info(TAG + 'beforeAll'); + rdbStore = await dataRdb.getRdbStore(context, STORE_CONFIG); + }) + beforeEach(async function () { + console.info(TAG + 'beforeEach'); + }) + afterEach(async function () { + console.info(TAG + 'afterEach'); + }) + afterAll(async function () { + console.info(TAG + 'afterAll'); + rdbStore = null + await dataRdb.deleteRdbStore(context, DB_NAME); + }) - console.log(TAG + "*************Unit Test Begin*************"); + console.log(TAG + "*************Unit Test Begin*************"); - it('SUB_DDM_PERF_RDB_version_001', 0, async function (done) { - let averageTime = 0; - let dbVersion = 1; - let startTime = new Date().getTime(); - for (var i = 0; i < BASE_COUNT; i++) { - dbVersion = rdbStore.version; - } - let endTime = new Date().getTime(); - averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; - console.info(TAG + " the version average time is: " + averageTime + " μs"); - expect(averageTime < BASE_LINE).assertTrue(); - done(); - }) + it('SUB_DDM_PERF_RDB_version_001', 0, async function (done) { + let averageTime = 0; + let dbVersion = 1; + let startTime = new Date().getTime(); + for (var i = 0; i < BASE_COUNT; i++) { + dbVersion = rdbStore.version; + } + let endTime = new Date().getTime(); + averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; + console.info(TAG + " the version average time is: " + averageTime + " μs"); + expect(averageTime < BASE_LINE).assertTrue(); + done(); + }) - it('SUB_DDM_PERF_RDB_transaction_commit_001', 0, async function (done) { - let averageTime = 0; - let startTime = new Date().getTime(); - for (var i = 0; i < BASE_COUNT; i++) { - rdbStore.beginTransaction(); - rdbStore.commit(); - } - let endTime = new Date().getTime(); - averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; - console.info(TAG + " the transaction_commit average time is: " + averageTime + " μs"); - expect(averageTime < BASE_LINE).assertTrue(); - done(); - }) + it('SUB_DDM_PERF_RDB_transaction_commit_001', 0, async function (done) { + let averageTime = 0; + let startTime = new Date().getTime(); + for (var i = 0; i < BASE_COUNT; i++) { + rdbStore.beginTransaction(); + rdbStore.commit(); + } + let endTime = new Date().getTime(); + averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; + console.info(TAG + " the transaction_commit average time is: " + averageTime + " μs"); + expect(averageTime < BASE_LINE).assertTrue(); + done(); + }) - it('SUB_DDM_PERF_RDB_transaction_rollback_001', 0, async function (done) { - let averageTime = 0; - let startTime = new Date().getTime(); - for (var i = 0; i < BASE_COUNT; i++) { - rdbStore.beginTransaction(); - rdbStore.rollBack(); - } - let endTime = new Date().getTime(); - averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; - console.info(TAG + " the transaction_rollback average time is: " + averageTime + " μs"); - expect(averageTime < BASE_LINE).assertTrue(); - done(); - console.info(TAG + "*************Unit Test End*************"); - }) + it('SUB_DDM_PERF_RDB_transaction_rollback_001', 0, async function (done) { + let averageTime = 0; + let startTime = new Date().getTime(); + for (var i = 0; i < BASE_COUNT; i++) { + rdbStore.beginTransaction(); + rdbStore.rollBack(); + } + let endTime = new Date().getTime(); + averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; + console.info(TAG + " the transaction_rollback average time is: " + averageTime + " μs"); + expect(averageTime < BASE_LINE).assertTrue(); + done(); + console.info(TAG + "*************Unit Test End*************"); + }) }) diff --git a/relational_store/test/js/relationalstore/performance/src/ResultSetPerf.js b/relational_store/test/js/relationalstore/performance/src/ResultSetPerf.js index 15ea1d0d..797a7906 100644 --- a/relational_store/test/js/relationalstore/performance/src/ResultSetPerf.js +++ b/relational_store/test/js/relationalstore/performance/src/ResultSetPerf.js @@ -13,18 +13,19 @@ * limitations under the License. */ -import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect, Assert } from 'deccjsunit/index'; -import dataRdb from '@ohos.data.rdb'; +import {describe, beforeAll, beforeEach, afterEach, afterAll, it, expect, Assert} from 'deccjsunit/index'; +import dataRdb from '@ohos.data.relationalStore'; import featureAbility from '@ohos.ability.featureAbility'; import deviceInfo from '@ohos.deviceInfo'; const TAG = "[RDB_RESULTSET_PERF]"; const CREATE_TABLE_TEST = "CREATE TABLE IF NOT EXISTS test (id INTEGER PRIMARY KEY AUTOINCREMENT, " -+ "name TEXT, age INTEGER, salary REAL, blobType BLOB)"; + + "name TEXT, age INTEGER, salary REAL, blobType BLOB)"; const DB_NAME = "resultSetPerf.db"; const STORE_CONFIG = { - name: DB_NAME, + name: DB_NAME, + securityLevel: dataRdb.SecurityLevel.S1 } let context = featureAbility.getContext(); var rdbStore = undefined; @@ -35,260 +36,254 @@ const BASE_LINE_PHONE = 1000; // callback phone base line const BASE_LINE = (deviceInfo.deviceType == "tablet") ? BASE_LINE_TABLE : BASE_LINE_PHONE; describe('resultSetPerf', function () { - beforeAll(async function () { - console.info(TAG + 'beforeAll'); - rdbStore = await dataRdb.getRdbStore(context, STORE_CONFIG, 1); - }) - beforeEach(async function () { - console.info(TAG + 'beforeEach'); - await rdbStore.executeSql(CREATE_TABLE_TEST, null); - await prepareTestData(); - }) - afterEach(async function () { - console.info(TAG + 'afterEach'); - await rdbStore.executeSql("drop table test"); - }) - afterAll(async function () { - console.info(TAG + 'afterAll'); - rdbStore = null; - await dataRdb.deleteRdbStore(context, DB_NAME); - }) + beforeAll(async function () { + console.info(TAG + 'beforeAll'); + rdbStore = await dataRdb.getRdbStore(context, STORE_CONFIG); + }) + beforeEach(async function () { + console.info(TAG + 'beforeEach'); + await rdbStore.executeSql(CREATE_TABLE_TEST, null); + await prepareTestData(); + }) + afterEach(async function () { + console.info(TAG + 'afterEach'); + await rdbStore.executeSql("drop table test"); + }) + afterAll(async function () { + console.info(TAG + 'afterAll'); + rdbStore = null; + await dataRdb.deleteRdbStore(context, DB_NAME); + }) - async function prepareTestData() { - console.info(TAG + "prepare for query performance test"); - var valueBuckets = []; - var u8 = new Uint8Array([1, 2, 3]) - var valueBucket = { - "name": "zhangsan", - "age": 18, - "salary": 100.5, - "blobType": u8, - } - for (let i = 0; i < BASE_COUNT; i++) { - valueBucket.age += i; - valueBuckets.push(valueBucket); - } - rdbStore.batchInsert("test", valueBuckets, function (err, insertNum) { - if (err) { - console.error(`batchInsert is failed, err: ${err}`); - return; - } - console.info(`batchInsert is successful, the number of values that were inserted = ${insertNum}`); - }) + async function prepareTestData() { + console.info(TAG + "prepare for query performance test"); + var valueBuckets = []; + var u8 = new Uint8Array([1, 2, 3]) + var valueBucket = { + "name": "zhangsan", + "age": 18, + "salary": 100.5, + "blobType": u8, } + for (let i = 0; i < BASE_COUNT; i++) { + valueBucket.age += i; + valueBuckets.push(valueBucket); + } + await rdbStore.batchInsert("test", valueBuckets); + } - console.log(TAG + "*************Unit Test Begin*************"); + console.log(TAG + "*************Unit Test Begin*************"); - it('SUB_DDM_PERF_RDB_ResultSet_GetColumnIndex_001', 0, async function (done) { - let predicates = new dataRdb.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates); - resultSet.goToFirstRow(); - let startTime = new Date().getTime(); - for (let i = 0; i < BASE_LINE; i++) { - resultSet.getColumnIndex("id"); - } - let endTime = new Date().getTime(); - let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; - console.info(TAG + " the ResultSet_GetColumnIndex average time is: " + averageTime + " μs"); - resultSet.close(); - expect(averageTime < BASE_LINE).assertTrue(); - done(); - }) + it('SUB_DDM_PERF_RDB_ResultSet_GetColumnIndex_001', 0, async function (done) { + let predicates = new dataRdb.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + resultSet.goToFirstRow(); + let startTime = new Date().getTime(); + for (let i = 0; i < BASE_LINE; i++) { + resultSet.getColumnIndex("id"); + } + let endTime = new Date().getTime(); + let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; + console.info(TAG + " the ResultSet_GetColumnIndex average time is: " + averageTime + " μs"); + resultSet.close(); + expect(averageTime < BASE_LINE).assertTrue(); + done(); + }) - it('SUB_DDM_PERF_RDB_ResultSet_GetColumnName_001', 0, async function (done) { - let predicates = new dataRdb.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates); - resultSet.goToFirstRow(); - let startTime = new Date().getTime() - for (let i = 0; i < BASE_COUNT; i++) { - resultSet.getColumnName(0); - } - let endTime = new Date().getTime(); - let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; - console.info(TAG + " the ResultSet_GetColumnName average time is: " + averageTime + " μs") - resultSet.close(); - expect(averageTime < BASE_LINE).assertTrue(); - done(); - }) + it('SUB_DDM_PERF_RDB_ResultSet_GetColumnName_001', 0, async function (done) { + let predicates = new dataRdb.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + resultSet.goToFirstRow(); + let startTime = new Date().getTime() + for (let i = 0; i < BASE_COUNT; i++) { + resultSet.getColumnName(0); + } + let endTime = new Date().getTime(); + let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; + console.info(TAG + " the ResultSet_GetColumnName average time is: " + averageTime + " μs") + resultSet.close(); + expect(averageTime < BASE_LINE).assertTrue(); + done(); + }) - it('SUB_DDM_PERF_RDB_ResultSet_GoTo_001', 0, async function (done) { - let predicates = new dataRdb.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates); - resultSet.goToFirstRow(); - let startTime = new Date().getTime() - for (let i = 0; i < BASE_COUNT; i++) { - resultSet.goTo(i % 2); - } - let endTime = new Date().getTime(); - let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; - console.info(TAG + " the ResultSet_GoTo average time is: " + averageTime + " μs") - resultSet.close(); - expect(averageTime < BASE_LINE).assertTrue(); - done(); - }) + it('SUB_DDM_PERF_RDB_ResultSet_GoTo_001', 0, async function (done) { + let predicates = new dataRdb.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + resultSet.goToFirstRow(); + let startTime = new Date().getTime() + for (let i = 0; i < BASE_COUNT; i++) { + resultSet.goTo(i % 2); + } + let endTime = new Date().getTime(); + let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; + console.info(TAG + " the ResultSet_GoTo average time is: " + averageTime + " μs") + resultSet.close(); + expect(averageTime < BASE_LINE).assertTrue(); + done(); + }) - it('SUB_DDM_PERF_RDB_ResultSet_GoToRow_001', 0, async function (done) { - let predicates = new dataRdb.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates); - resultSet.goToFirstRow(); - let startTime = new Date().getTime(); - for (let i = 0; i < BASE_COUNT; i++) { - resultSet.goToRow(1); - } - let endTime = new Date().getTime(); - let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; - console.info(TAG + " the ResultSet_GoToRow average time is: " + averageTime + " μs"); - resultSet.close(); - expect(averageTime < BASE_LINE).assertTrue(); - done(); - }) + it('SUB_DDM_PERF_RDB_ResultSet_GoToRow_001', 0, async function (done) { + let predicates = new dataRdb.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + resultSet.goToFirstRow(); + let startTime = new Date().getTime(); + for (let i = 0; i < BASE_COUNT; i++) { + resultSet.goToRow(1); + } + let endTime = new Date().getTime(); + let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; + console.info(TAG + " the ResultSet_GoToRow average time is: " + averageTime + " μs"); + resultSet.close(); + expect(averageTime < BASE_LINE).assertTrue(); + done(); + }) - it('SUB_DDM_PERF_RDB_ResultSet_GoToFirstRow_001', 0, async function (done) { - let predicates = new dataRdb.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates); - let startTime = new Date().getTime(); - for (let i = 0; i < BASE_COUNT; i++) { - resultSet.goToFirstRow(); - } - let endTime = new Date().getTime(); - let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; - console.info(TAG + " the ResultSet_GoToFirstRow average time is: " + averageTime + " μs"); - resultSet.close(); - expect(averageTime < BASE_LINE).assertTrue(); - done(); - }) + it('SUB_DDM_PERF_RDB_ResultSet_GoToFirstRow_001', 0, async function (done) { + let predicates = new dataRdb.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + let startTime = new Date().getTime(); + for (let i = 0; i < BASE_COUNT; i++) { + resultSet.goToFirstRow(); + } + let endTime = new Date().getTime(); + let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; + console.info(TAG + " the ResultSet_GoToFirstRow average time is: " + averageTime + " μs"); + resultSet.close(); + expect(averageTime < BASE_LINE).assertTrue(); + done(); + }) - it('SUB_DDM_PERF_RDB_ResultSet_GoToLastRow_001', 0, async function (done) { - let predicates = new dataRdb.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates); - let startTime = new Date().getTime(); - for (let i = 0; i < BASE_COUNT; i++) { - resultSet.goToLastRow(); - } - let endTime = new Date().getTime(); - let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; - console.info(TAG + " the ResultSet_GoToLastRow average time is: " + averageTime + " μs"); - resultSet.close(); - expect(averageTime < BASE_LINE).assertTrue(); - done(); - }) + it('SUB_DDM_PERF_RDB_ResultSet_GoToLastRow_001', 0, async function (done) { + let predicates = new dataRdb.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + let startTime = new Date().getTime(); + for (let i = 0; i < BASE_COUNT; i++) { + resultSet.goToLastRow(); + } + let endTime = new Date().getTime(); + let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; + console.info(TAG + " the ResultSet_GoToLastRow average time is: " + averageTime + " μs"); + resultSet.close(); + expect(averageTime < BASE_LINE).assertTrue(); + done(); + }) - it('SUB_DDM_PERF_RDB_ResultSet_GoToNextRow_001', 0, async function (done) { - let predicates = new dataRdb.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates); - resultSet.goToFirstRow(); - let startTime = new Date().getTime(); - for (let i = 0; i < BASE_COUNT; i++) { - resultSet.goToNextRow(); - } - let endTime = new Date().getTime(); - let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; - console.info(TAG + " the ResultSet_GoToNextRow average time is: " + averageTime + " μs") - resultSet.close(); - expect(averageTime < BASE_LINE).assertTrue(); - done(); - }) + it('SUB_DDM_PERF_RDB_ResultSet_GoToNextRow_001', 0, async function (done) { + let predicates = new dataRdb.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + resultSet.goToFirstRow(); + let startTime = new Date().getTime(); + for (let i = 0; i < BASE_COUNT; i++) { + resultSet.goToNextRow(); + } + let endTime = new Date().getTime(); + let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; + console.info(TAG + " the ResultSet_GoToNextRow average time is: " + averageTime + " μs") + resultSet.close(); + expect(averageTime < BASE_LINE).assertTrue(); + done(); + }) - it('SUB_DDM_PERF_RDB_ResultSet_GoToPreviousRow_001', 0, async function (done) { - let predicates = new dataRdb.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates); - resultSet.goToLastRow(); - let startTime = new Date().getTime(); - for (let i = 0; i < BASE_COUNT; i++) { - resultSet.goToPreviousRow(); - } - let endTime = new Date().getTime(); - let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; - console.info(TAG + " the ResultSet_GoToPreviousRow average time is: " + averageTime + " μs"); - resultSet.close(); - expect(averageTime < BASE_LINE).assertTrue(); - done(); - }) + it('SUB_DDM_PERF_RDB_ResultSet_GoToPreviousRow_001', 0, async function (done) { + let predicates = new dataRdb.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + resultSet.goToLastRow(); + let startTime = new Date().getTime(); + for (let i = 0; i < BASE_COUNT; i++) { + resultSet.goToPreviousRow(); + } + let endTime = new Date().getTime(); + let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; + console.info(TAG + " the ResultSet_GoToPreviousRow average time is: " + averageTime + " μs"); + resultSet.close(); + expect(averageTime < BASE_LINE).assertTrue(); + done(); + }) - it('SUB_DDM_PERF_RDB_ResultSet_GetBlob_001', 0, async function (done) { - let predicates = new dataRdb.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates); - let columnIndex = resultSet.getColumnIndex("blobType"); - resultSet.goToFirstRow(); - let startTime = new Date().getTime() - for (let i = 0; i < BASE_COUNT; i++) { - resultSet.getBlob(columnIndex); - } - let endTime = new Date().getTime(); - let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; - console.info(TAG + " the ResultSet_GetBlob average time is: " + averageTime + " μs"); - resultSet.close(); - expect(averageTime < BASE_LINE).assertTrue(); - done(); - }) + it('SUB_DDM_PERF_RDB_ResultSet_GetBlob_001', 0, async function (done) { + let predicates = new dataRdb.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + let columnIndex = resultSet.getColumnIndex("blobType"); + resultSet.goToFirstRow(); + let startTime = new Date().getTime() + for (let i = 0; i < BASE_COUNT; i++) { + resultSet.getBlob(columnIndex); + } + let endTime = new Date().getTime(); + let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; + console.info(TAG + " the ResultSet_GetBlob average time is: " + averageTime + " μs"); + resultSet.close(); + expect(averageTime < BASE_LINE).assertTrue(); + done(); + }) - it('SUB_DDM_PERF_RDB_ResultSet_GetString_001', 0, async function (done) { - let predicates = new dataRdb.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates); - let columnIndex = resultSet.getColumnIndex("name"); - let flag = resultSet.goToFirstRow(); - let startTime = new Date().getTime(); - for (var i = 0; i < SPECIAL_BASE_COUNT; i++) { - resultSet.getString(columnIndex); - } - let endTime = new Date().getTime(); - let averageTime = ((endTime - startTime) * 1000) / SPECIAL_BASE_COUNT; - console.info(TAG + " the ResultSet_GetString average time is: " + averageTime + " μs"); - resultSet.close(); - expect(averageTime < BASE_LINE).assertTrue(); - done() - }) + it('SUB_DDM_PERF_RDB_ResultSet_GetString_001', 0, async function (done) { + let predicates = new dataRdb.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + let columnIndex = resultSet.getColumnIndex("name"); + let flag = resultSet.goToFirstRow(); + let startTime = new Date().getTime(); + for (var i = 0; i < SPECIAL_BASE_COUNT; i++) { + resultSet.getString(columnIndex); + } + let endTime = new Date().getTime(); + let averageTime = ((endTime - startTime) * 1000) / SPECIAL_BASE_COUNT; + console.info(TAG + " the ResultSet_GetString average time is: " + averageTime + " μs"); + resultSet.close(); + expect(averageTime < BASE_LINE).assertTrue(); + done() + }) - it('SUB_DDM_PERF_RDB_ResultSet_GetLong_001', 0, async function (done) { - let predicates = new dataRdb.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates); - let columnIndex = resultSet.getColumnIndex("age"); - resultSet.goToFirstRow(); - let startTime = new Date().getTime(); - for (let i = 0; i < BASE_COUNT; i++) { - resultSet.getLong(columnIndex); - } - let endTime = new Date().getTime(); - let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; - console.info(TAG + " the ResultSet_GetLong average time is: " + averageTime + " μs") - resultSet.close(); - expect(averageTime < BASE_LINE).assertTrue(); - done(); - }) + it('SUB_DDM_PERF_RDB_ResultSet_GetLong_001', 0, async function (done) { + let predicates = new dataRdb.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + let columnIndex = resultSet.getColumnIndex("age"); + resultSet.goToFirstRow(); + let startTime = new Date().getTime(); + for (let i = 0; i < BASE_COUNT; i++) { + resultSet.getLong(columnIndex); + } + let endTime = new Date().getTime(); + let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; + console.info(TAG + " the ResultSet_GetLong average time is: " + averageTime + " μs") + resultSet.close(); + expect(averageTime < BASE_LINE).assertTrue(); + done(); + }) - it('SUB_DDM_PERF_RDB_ResultSet_GetDouble_001', 0, async function (done) { - let predicates = new dataRdb.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates); - let columnIndex = resultSet.getColumnIndex("salary"); - resultSet.goToFirstRow(); - let startTime = new Date().getTime() - for (let i = 0; i < BASE_COUNT; i++) { - resultSet.getDouble(columnIndex); - } - let endTime = new Date().getTime(); - let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; - console.info(TAG + " the ResultSet_GetDouble average time is: " + averageTime + " μs") - resultSet.close(); - expect(averageTime < BASE_LINE).assertTrue(); - done(); - }) + it('SUB_DDM_PERF_RDB_ResultSet_GetDouble_001', 0, async function (done) { + let predicates = new dataRdb.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + let columnIndex = resultSet.getColumnIndex("salary"); + resultSet.goToFirstRow(); + let startTime = new Date().getTime() + for (let i = 0; i < BASE_COUNT; i++) { + resultSet.getDouble(columnIndex); + } + let endTime = new Date().getTime(); + let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; + console.info(TAG + " the ResultSet_GetDouble average time is: " + averageTime + " μs") + resultSet.close(); + expect(averageTime < BASE_LINE).assertTrue(); + done(); + }) - it('SUB_DDM_PERF_RDB_ResultSet_IsColumnNull_001', 0, async function (done) { - let predicates = new dataRdb.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates); - let columnIndex = resultSet.getColumnIndex("salary"); - resultSet.goToFirstRow(); - let startTime = new Date().getTime() - for (let i = 0; i < BASE_COUNT; i++) { - resultSet.isColumnNull(columnIndex); - } - let endTime = new Date().getTime(); - let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; - console.info(TAG + " the ResultSet_IsColumnNull average time is: " + averageTime + " μs"); - resultSet.close(); - expect(averageTime < BASE_LINE).assertTrue(); - done(); - }) + it('SUB_DDM_PERF_RDB_ResultSet_IsColumnNull_001', 0, async function (done) { + let predicates = new dataRdb.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + let columnIndex = resultSet.getColumnIndex("salary"); + resultSet.goToFirstRow(); + let startTime = new Date().getTime() + for (let i = 0; i < BASE_COUNT; i++) { + resultSet.isColumnNull(columnIndex); + } + let endTime = new Date().getTime(); + let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; + console.info(TAG + " the ResultSet_IsColumnNull average time is: " + averageTime + " μs"); + resultSet.close(); + expect(averageTime < BASE_LINE).assertTrue(); + done(); + }) - console.info(TAG + "*************Unit Test End*************"); + console.info(TAG + "*************Unit Test End*************"); }) \ No newline at end of file diff --git a/relational_store/test/js/relationalstore/performance/src/SceneGetValuesBucketPerf.js b/relational_store/test/js/relationalstore/performance/src/SceneGetValuesBucketPerf.js new file mode 100644 index 00000000..33aa0de7 --- /dev/null +++ b/relational_store/test/js/relationalstore/performance/src/SceneGetValuesBucketPerf.js @@ -0,0 +1,197 @@ +/* + * 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. + */ + +import {describe, beforeAll, beforeEach, afterEach, afterAll, it, expect, Assert} from 'deccjsunit/index'; +import dataRdb from '@ohos.data.relationalStore'; +import featureAbility from '@ohos.ability.featureAbility'; + +const TAG = "[RDB_RESULTSET_PERF]"; +const CREATE_TABLE_TEST = "CREATE TABLE test (" + + "data01 TEXT, data02 INTEGER, data03 FLOAT, data04 BLOB, data05 BOOLEAN, " + + "data06 TEXT, data07 INTEGER, data08 FLOAT, data09 BLOB, data10 BOOLEAN, " + + "data11 TEXT, data12 INTEGER, data13 FLOAT, data14 BLOB, data15 BOOLEAN, " + + "data16 TEXT, data17 INTEGER, data18 FLOAT, data19 BLOB, data20 BOOLEAN" + + ");"; + +const FIELDS = ["data01", "data02", "data03", "data04", "data05", "data06", "data07", "data08", "data09", "data10", + "data11", "data12", "data13", "data14", "data15", "data16", "data17", "data18", "data19", "data20"] + +function CREATE_STRING(len) { + let result = ''; + for (let i = 0; i < len; i++) { + result += 'a'; + } + return result; +} + +const CONST_STRING_VALUE = CREATE_STRING(127); + +function CREATE_UINT8_ARRAY(len) { + let result = new Uint8Array(len); + for (let i = 0; i < len; i++) { + result[i] = 1; + } + return result; +} + +const CONST_UINT8_ARRAY = CREATE_UINT8_ARRAY(127); + +const DB_NAME = "resultSetPerf.db"; +const STORE_CONFIG = { + name: DB_NAME, + securityLevel: dataRdb.SecurityLevel.S3 +} + +let context = featureAbility.getContext(); +let rdbStore = undefined; +const BASE_COUNT = 2000; // loop times + +describe('SceneGetValuesBucketPerf', function () { + beforeAll(async function () { + console.info(TAG + 'beforeAll'); + rdbStore = await dataRdb.getRdbStore(context, STORE_CONFIG); + await rdbStore.executeSql(CREATE_TABLE_TEST); + await prepareTestData(); + }) + + beforeEach(async function () { + console.info(TAG + 'beforeEach'); + }) + + afterEach(async function () { + console.info(TAG + 'afterEach'); + }) + + afterAll(async function () { + console.info(TAG + 'afterAll'); + await rdbStore.executeSql("drop table test"); + rdbStore = null; + await dataRdb.deleteRdbStore(context, DB_NAME); + }) + + async function prepareTestData() { + console.info(TAG + "prepare for query performance test"); + let valueBuckets = []; + let valueBucket = { + data01: CONST_STRING_VALUE, + data02: 10001, + data03: 101.5, + data04: CONST_UINT8_ARRAY, + data05: false, + data06: CONST_STRING_VALUE, + data07: 10002, + data08: 102.5, + data09: CONST_UINT8_ARRAY, + data10: true, + data11: CONST_STRING_VALUE, + data12: 10003, + data13: 103.5, + data14: CONST_UINT8_ARRAY, + data15: false, + data16: CONST_STRING_VALUE, + data17: 10004, + data18: 104.5, + data19: CONST_UINT8_ARRAY, + data20: true + } + for (let i = 0; i < BASE_COUNT; i++) { + valueBuckets.push(valueBucket); + } + await rdbStore.batchInsert("test", valueBuckets) + } + + it('Scene_GetValuesBucket_0001', 0, async function (done) { + console.log(TAG + "************* Scene_GetValuesBucket_0001 start *************"); + let predicates = await new dataRdb.RdbPredicates("test") + let resultSet = await rdbStore.query(predicates) + expect(2000).assertEqual(resultSet.rowCount); + + let startTime = new Date().getTime(); + let allValues = new Array(); + let i = 0; + while (resultSet.goToNextRow()) { + let values = resultSet.getRow(); + allValues[i++] = values; + } + resultSet.close(); + let endTime = new Date().getTime(); + let averageTime = (endTime - startTime); + console.info(TAG + " the Scene_GetValuesBucket_0001 average time is: " + averageTime + " ms"); + expect(2000).assertEqual(allValues.length); + expect(averageTime).assertLess(600); + + expect(CONST_STRING_VALUE).assertEqual(allValues[0]["data01"]); + done(); + console.log(TAG + "************* Scene_GetValuesBucket_0001 end *************"); + }) + + /** + * @tc.name RDB Backup Restore test + * @tc.number SUB_DDM_RDB_JS_RdbBackupRestoreTest_0010 + * @tc.desc RDB backup and restore function test + */ + it('Scene_GetValuesBucket_0002', 0, async function (done) { + console.log(TAG + "************* Scene_GetValuesBucket_0002 start *************"); + let predicates = await new dataRdb.RdbPredicates("test") + let resultSet = await rdbStore.query(predicates) + expect(2000).assertEqual(resultSet.rowCount); + + let startTime = new Date().getTime(); + let allValues = new Array(2000); + + let i = 0; + let indexes = new Array(20); + while (resultSet.goToNextRow()) { + let values = new Array(); + + if (i == 0) { + for (let i = 0; i < 20; i++) { + indexes[i] = resultSet.getColumnIndex(FIELDS[i]); + } + } + + for (let i = 0; i < 20; i++) { + switch (resultSet.getColumnType(indexes[i])) { + case 0: // TYPE_NULL + values[FIELDS[i]] = null; + break; + case 1: // TYPE_INTEGER + values[FIELDS[i]] = resultSet.getInt(indexes[i]); + break; + case 2: // TYPE_FLOAT + values[FIELDS[i]] = resultSet.getDouble(indexes[i]); + break; + case 3: // TYPE_STRING + values[FIELDS[i]] = resultSet.getString(indexes[i]); + break; + case 4: // TYPE_BLOB + values[FIELDS[i]] = resultSet.getBlob(indexes[i]); + break; + } + } + allValues[i++] = values; + } + resultSet.close(); + let endTime = new Date().getTime(); + let averageTime = (endTime - startTime); + console.info(TAG + " the Scene_GetValuesBucket_0002 average time is: " + averageTime + " ms"); + expect(2000).assertEqual(allValues.length); + expect(averageTime).assertLess(1500); + + expect(CONST_STRING_VALUE).assertEqual(allValues[0]["data01"]); + done(); + console.log(TAG + "************* Scene_GetValuesBucket_0002 end *************"); + }) +}) \ No newline at end of file diff --git a/relational_store/test/js/relationalstore/unittest/src/RdbStoreResultSetGetRow.test.js b/relational_store/test/js/relationalstore/unittest/src/RdbStoreResultSetGetRow.test.js new file mode 100644 index 00000000..76d4c167 --- /dev/null +++ b/relational_store/test/js/relationalstore/unittest/src/RdbStoreResultSetGetRow.test.js @@ -0,0 +1,182 @@ +/* + * 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. + */ + +import {describe, beforeAll, beforeEach, afterEach, afterAll, it, expect} from 'deccjsunit/index' +import data_relationalStore from '@ohos.data.relationalStore'; +import ability_featureAbility from '@ohos.ability.featureAbility' + +var context = ability_featureAbility.getContext() + +const TAG = "[RELATIONAL_STORE_JSKITS_TEST]" + +const STORE_CONFIG = { + name: "stepResultSet_getRow_test.db", + securityLevel: data_relationalStore.SecurityLevel.S1, +} +let rdbStore +describe('rdbStoreResultSetGetRowTest', function () { + beforeAll(async function () { + console.info(TAG + 'beforeAll') + await data_relationalStore.deleteRdbStore(context, "stepResultSet_getRow_test.db"); + rdbStore = await data_relationalStore.getRdbStore(context, STORE_CONFIG); + }) + + beforeEach(async function () { + console.info(TAG + 'beforeEach') + await rdbStore.executeSql("CREATE TABLE test (id INTEGER PRIMARY KEY AUTOINCREMENT, data1 TEXT, " + + "data2 INTEGER, data3 FLOAT, data4 BLOB, data5 BOOLEAN);"); + }) + + afterEach(async function () { + console.info(TAG + 'afterEach') + await rdbStore.executeSql("DROP TABLE IF EXISTS test"); + }) + + afterAll(async function () { + console.info(TAG + 'afterAll') + await data_relationalStore.deleteRdbStore(context, "stepResultSet_getRow_test.db"); + }) + + console.log(TAG + "*************Unit Test Begin*************"); + + /** + * @tc.name rdb store resultSet getRow test + * @tc.number rdbStoreResultSetGetRowTest0001 + * @tc.desc resultSet getRow test + */ + it('rdbStoreResultSetGetRowTest0001', 0, async function (done) { + console.log(TAG + "************* rdbStoreResultSetGetRowTest0001 start *************"); + let valueBucket = { + id: 1 + }; + let rowId = await rdbStore.insert("test", valueBucket); + expect(1).assertEqual(rowId); + + let predicates = await new data_relationalStore.RdbPredicates("test") + let resultSet = await rdbStore.query(predicates) + expect(true).assertEqual(resultSet.goToFirstRow()); + + let valueBucket_ret = resultSet.getRow(); + + expect(1).assertEqual(valueBucket_ret["id"]); + expect(null).assertEqual(valueBucket_ret["data1"]); + expect(null).assertEqual(valueBucket_ret["data2"]); + expect(null).assertEqual(valueBucket_ret["data3"]); + expect(null).assertEqual(valueBucket_ret["data4"]); + expect(null).assertEqual(valueBucket_ret["data5"]); + + done(); + console.log(TAG + "************* rdbStoreResultSetGetRowTest0001 end *************"); + }) + + /** + * @tc.name rdb store resultSet getRow test + * @tc.number rdbStoreResultSetGetRowTest0002 + * @tc.desc resultSet getRow test + */ + it('rdbStoreResultSetGetRowTest0002', 0, async function (done) { + console.log(TAG + "************* rdbStoreResultSetGetRowTest0002 start *************"); + let valueBucket = { + data1: null, + data2: undefined, + data4: undefined, + data5: null + }; + let rowId = await rdbStore.insert("test", valueBucket); + expect(1).assertEqual(rowId); + + let predicates = await new data_relationalStore.RdbPredicates("test") + let resultSet = await rdbStore.query(predicates) + expect(true).assertEqual(resultSet.goToFirstRow()); + + let valueBucket_ret = resultSet.getRow(); + + expect(1).assertEqual(valueBucket_ret["id"]); + expect(null).assertEqual(valueBucket_ret["data1"]); + expect(null).assertEqual(valueBucket_ret["data2"]); + expect(null).assertEqual(valueBucket_ret["data3"]); + expect(null).assertEqual(valueBucket_ret["data4"]); + expect(null).assertEqual(valueBucket_ret["data5"]); + + done(); + console.log(TAG + "************* rdbStoreResultSetGetRowTest0002 end *************"); + }) + + /** + * @tc.name rdb store resultSet getRow test + * @tc.number rdbStoreResultSetGetRowTest0003 + * @tc.desc resultSet getRow test + */ + it('rdbStoreResultSetGetRowTest0003', 0, async function (done) { + console.log(TAG + "************* rdbStoreResultSetGetRowTest0003 start *************"); + let valueBucket = { + data1: "hello", + data2: 10, + data3: 1.0, + data4: new Uint8Array([1, 2, 3, 4]), + data5: true, + }; + let rowId = await rdbStore.insert("test", valueBucket); + expect(1).assertEqual(rowId); + + let predicates = await new data_relationalStore.RdbPredicates("test") + let resultSet = await rdbStore.query(predicates) + expect(true).assertEqual(resultSet.goToFirstRow()); + + let valueBucket_ret = resultSet.getRow(); + + expect(1).assertEqual(valueBucket_ret.id); + expect("hello").assertEqual(valueBucket_ret.data1); + expect(10).assertEqual(valueBucket_ret.data2); + expect(1.0).assertEqual(valueBucket_ret.data3); + expect(4).assertEqual(valueBucket_ret.data4[3]); + expect(1).assertEqual(valueBucket_ret.data5); + + done(); + console.log(TAG + "************* rdbStoreResultSetGetRowTest0003 end *************"); + }) + + /** + * @tc.name rdb store resultSet getRow test + * @tc.number rdbStoreResultSetGetRowTest0004 + * @tc.desc resultSet getRow test + */ + it('rdbStoreResultSetGetRowTest0004', 0, async function (done) { + console.log(TAG + "************* rdbStoreResultSetGetRowTest0004 start *************"); + let valueBucket = { + "data1": "", + "data2": 10, + "data3": 1.0, + "data4": new Uint8Array([1, 2, 3, 4]), + "data5": true, + }; + let rowId = await rdbStore.insert("test", valueBucket); + expect(1).assertEqual(rowId); + + let predicates = await new data_relationalStore.RdbPredicates("test") + let resultSet = await rdbStore.query(predicates, ["data1", "data2"]) + expect(true).assertEqual(resultSet.goToFirstRow()); + + let valueBucket_ret = resultSet.getRow(); + + expect("").assertEqual(valueBucket_ret.data1); + expect(undefined).assertEqual(valueBucket_ret.data3); + expect(undefined).assertEqual(valueBucket_ret.data4); + + done(); + console.log(TAG + "************* rdbStoreResultSetGetRowTest0004 end *************"); + }) + console.log(TAG + "*************Unit Test End*************"); +}) \ No newline at end of file diff --git a/relational_store/test/js/relationalstore/unittest/src/RdbStoreResultSetJsunit.test.js b/relational_store/test/js/relationalstore/unittest/src/RdbStoreResultSetJsunit.test.js index 1fa6b5ee..fb02dbec 100644 --- a/relational_store/test/js/relationalstore/unittest/src/RdbStoreResultSetJsunit.test.js +++ b/relational_store/test/js/relationalstore/unittest/src/RdbStoreResultSetJsunit.test.js @@ -1974,7 +1974,7 @@ describe('rdbResultSetTest', function () { expect("").assertEqual(resultSet.getString(1)) } } catch (e) { - expect(e.code).assertEqual("14800000"); + expect(e.code).assertEqual("14800013"); } resultSet.close() expect(true).assertEqual(resultSet.isClosed) @@ -2015,7 +2015,7 @@ describe('rdbResultSetTest', function () { expect("").assertEqual(resultSet.getString(1)) } } catch (e) { - expect(e.code).assertEqual("14800000"); + expect(e.code).assertEqual("14800013"); } resultSet.close() @@ -2274,43 +2274,5 @@ describe('rdbResultSetTest', function () { console.log(TAG + "************* testBigData0014 end *************"); }) - - /** - * @tc.name resultSet Maximum read connections normal test - * @tc.number Maximum_Read_Connections_0001 - * @tc.desc resultSet getBlob normal test - */ - it('testMaximumReadConnections0001', 0, async function (done) { - console.log(TAG + "************* testMaximumReadConnections0002 start *************"); - - try{ - let resultSet1 = await rdbStore.queryByStep("SELECT ?, ? FROM test", ["id", "data1"]) - expect(true).assertEqual(resultSet1.goToFirstRow()) - - let resultSet2 = await rdbStore.queryByStep("SELECT ?, ? FROM test", ["id", "data1"]) - expect(true).assertEqual(resultSet2.goToFirstRow()) - - let resultSet3 = await rdbStore.queryByStep("SELECT ?, ? FROM test", ["id", "data1"]) - expect(true).assertEqual(resultSet3.goToFirstRow()) - - let resultSet4 = await rdbStore.queryByStep("SELECT ?, ? FROM test", ["id", "data1"]) - expect(true).assertEqual(resultSet4.goToFirstRow()) - - resultSet1.close(); - resultSet2.close(); - resultSet3.close(); - resultSet4.close(); - - resultSet1 = null; - resultSet2 = null; - resultSet3 = null; - resultSet4 = null; - } catch (e) { - expect(null).assertFail(); - } - done(); - console.log(TAG + "************* testMaximumReadConnections0001 end *************"); - }) - console.log(TAG + "*************Unit Test End*************"); }) \ No newline at end of file diff --git a/relational_store/test/native/rdb/BUILD.gn b/relational_store/test/native/rdb/BUILD.gn index 3bed308b..f6d223da 100644 --- a/relational_store/test/native/rdb/BUILD.gn +++ b/relational_store/test/native/rdb/BUILD.gn @@ -52,6 +52,7 @@ ohos_unittest("NativeRdbTest") { "unittest/rdb_predicates_join_test.cpp", "unittest/rdb_predicates_test.cpp", "unittest/rdb_sqlite_shared_result_set_test.cpp", + "unittest/rdb_step_result_get_row_test.cpp", "unittest/rdb_step_result_set_test.cpp", "unittest/rdb_store_concurrent_test.cpp", "unittest/rdb_store_config_test.cpp", diff --git a/relational_store/test/native/rdb/unittest/rdb_execute_test.cpp b/relational_store/test/native/rdb/unittest/rdb_execute_test.cpp index cec0a0d9..9b486e43 100644 --- a/relational_store/test/native/rdb/unittest/rdb_execute_test.cpp +++ b/relational_store/test/native/rdb/unittest/rdb_execute_test.cpp @@ -35,12 +35,10 @@ public: static const std::string DATABASE_NAME; static std::shared_ptr store; - static const int E_SQLITE_ERROR; // errno SQLITE_ERROR }; const std::string RdbExecuteTest::DATABASE_NAME = RDB_TEST_PATH + "execute_test.db"; std::shared_ptr RdbExecuteTest::store = nullptr; -const int RdbExecuteTest::E_SQLITE_ERROR = -1; // errno SQLITE_ERROR class ExecuteTestOpenCallback : public RdbOpenCallback { public: diff --git a/relational_store/test/native/rdb/unittest/rdb_sqlite_shared_result_set_test.cpp b/relational_store/test/native/rdb/unittest/rdb_sqlite_shared_result_set_test.cpp index 8b3853db..f3c28b33 100644 --- a/relational_store/test/native/rdb/unittest/rdb_sqlite_shared_result_set_test.cpp +++ b/relational_store/test/native/rdb/unittest/rdb_sqlite_shared_result_set_test.cpp @@ -36,12 +36,10 @@ public: static const std::string DATABASE_NAME; static std::shared_ptr store; - static const int E_SQLITE_ERROR; }; const std::string RdbSqliteSharedResultSetTest::DATABASE_NAME = RDB_TEST_PATH + "shared_test.db"; std::shared_ptr RdbSqliteSharedResultSetTest::store = nullptr; -const int RdbSqliteSharedResultSetTest::E_SQLITE_ERROR = -1; class SqliteSharedOpenCallback : public RdbOpenCallback { public: @@ -943,4 +941,76 @@ HWTEST_F(RdbSqliteSharedResultSetTest, Sqlite_Shared_Result_Set_018, TestSize.Le resultSet->Close(); bool closeFlag = resultSet->IsClosed(); EXPECT_EQ(closeFlag, true); +} + +/* * + * @tc.name: Sqlite_Shared_Result_Set_019 + * @tc.desc: normal testcase of SqliteSharedResultSet for GetRow + * @tc.type: FUNC + * @tc.require: AR000FKD4F + */ +HWTEST_F(RdbSqliteSharedResultSetTest, Sqlite_Shared_Result_Set_019, TestSize.Level1) +{ + GenerateDefaultTable(); + std::vector selectionArgs; + std::unique_ptr resultSet = + RdbSqliteSharedResultSetTest::store->QuerySql("SELECT * FROM test", selectionArgs); + EXPECT_NE(resultSet, nullptr); + + EXPECT_EQ(E_OK, resultSet->GoToFirstRow()); + + int iRet = E_ERROR; + RowEntity rowEntity; + iRet = resultSet->GetRow(rowEntity); + EXPECT_EQ(E_OK, iRet); + + int idValue = rowEntity.Get("id"); + std::string data1Value = rowEntity.Get("data1"); + int data2Value = rowEntity.Get("data2"); + double data3Value = rowEntity.Get("data3"); + std::vector data4Value = rowEntity.Get("data4"); + EXPECT_EQ(1, idValue); + EXPECT_EQ("hello", data1Value); + EXPECT_EQ(10, data2Value); + EXPECT_EQ(1.0, data3Value); + EXPECT_EQ(66, data4Value[0]); + + int idValueByIndex = rowEntity.Get(0); + std::string data1ValueByIndex = rowEntity.Get(1); + int data2ValueByIndex = rowEntity.Get(2); + double data3ValueByIndex = rowEntity.Get(3); + std::vector data4ValueByIndex = rowEntity.Get(4); + EXPECT_EQ(1, idValueByIndex); + EXPECT_EQ("hello", data1ValueByIndex); + EXPECT_EQ(10, data2ValueByIndex); + EXPECT_EQ(1.0, data3ValueByIndex); + EXPECT_EQ(66, data4ValueByIndex[0]); +} + +/* * + * @tc.name: Sqlite_Shared_Result_Set_020 + * @tc.desc: normal testcase of SqliteSharedResultSet for GetRow + * @tc.type: FUNC + * @tc.require: AR000FKD4F + */ +HWTEST_F(RdbSqliteSharedResultSetTest, Sqlite_Shared_Result_Set_020, TestSize.Level1) +{ + GenerateDefaultTable(); + std::vector selectionArgs; + std::unique_ptr resultSet = + RdbSqliteSharedResultSetTest::store->QuerySql("SELECT data1, data2 FROM test", selectionArgs); + EXPECT_NE(resultSet, nullptr); + + EXPECT_EQ(E_OK, resultSet->GoToFirstRow()); + + int iRet = E_ERROR; + RowEntity rowEntity; + iRet = resultSet->GetRow(rowEntity); + EXPECT_EQ(E_OK, iRet); + + std::string data1Value = rowEntity.Get("data1"); + EXPECT_EQ("hello", data1Value); + + std::string data1ValueByIndex = rowEntity.Get(0); + EXPECT_EQ("hello", data1ValueByIndex); } \ No newline at end of file diff --git a/relational_store/test/native/rdb/unittest/rdb_step_result_get_row_test.cpp b/relational_store/test/native/rdb/unittest/rdb_step_result_get_row_test.cpp new file mode 100644 index 00000000..6b564e01 --- /dev/null +++ b/relational_store/test/native/rdb/unittest/rdb_step_result_get_row_test.cpp @@ -0,0 +1,254 @@ +/* + * 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. + */ + +#include + +#include + +#include "common.h" +#include "logger.h" +#include "rdb_errno.h" +#include "rdb_helper.h" +#include "rdb_open_callback.h" + +using namespace testing::ext; +using namespace OHOS::NativeRdb; + +class RdbStepResultSetGetRowTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + + static const std::string DATABASE_NAME; + static std::shared_ptr store; +}; + +const std::string RdbStepResultSetGetRowTest::DATABASE_NAME = RDB_TEST_PATH + "stepResultSet_getRow_test.db"; +std::shared_ptr RdbStepResultSetGetRowTest::store = nullptr; + +class RdbStepResultSetGetOpenCallback : public RdbOpenCallback { +public: + int OnCreate(RdbStore &rdbStore) override; + int OnUpgrade(RdbStore &rdbStore, int oldVersion, int newVersion) override; +}; + +int RdbStepResultSetGetOpenCallback::OnCreate(RdbStore &store) +{ + return E_OK; +} + +int RdbStepResultSetGetOpenCallback::OnUpgrade(RdbStore &store, int oldVersion, int newVersion) +{ + return E_OK; +} + +void RdbStepResultSetGetRowTest::SetUpTestCase(void) +{ + int errCode = E_OK; + RdbHelper::DeleteRdbStore(DATABASE_NAME); + RdbStoreConfig config(RdbStepResultSetGetRowTest::DATABASE_NAME); + RdbStepResultSetGetOpenCallback helper; + RdbStepResultSetGetRowTest::store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_NE(RdbStepResultSetGetRowTest::store, nullptr); + EXPECT_EQ(errCode, E_OK); +} + +void RdbStepResultSetGetRowTest::TearDownTestCase(void) +{ + RdbHelper::ClearCache(); + RdbHelper::DeleteRdbStore(RdbStepResultSetGetRowTest::DATABASE_NAME); +} + +void RdbStepResultSetGetRowTest::SetUp(void) +{ + store->ExecuteSql("CREATE TABLE test (id INTEGER PRIMARY KEY AUTOINCREMENT, data1 TEXT, " + "data2 INTEGER, data3 FLOAT, data4 BLOB, data5 BOOLEAN);"); +} + +void RdbStepResultSetGetRowTest::TearDown(void) +{ + store->ExecuteSql("DROP TABLE IF EXISTS test"); +} + +/* * + * @tc.name: RdbStore_StepResultSet_GetRow_001 + * @tc.desc: test StepResultSet GetRow + * @tc.type: FUNC + * @tc.require: AR000FKD4F + */ +HWTEST_F(RdbStepResultSetGetRowTest, RdbStore_StepResultSet_GetRow_001, TestSize.Level1) +{ + int64_t rowId; + ValuesBucket valuesBucket; + valuesBucket.PutInt("id", ValueObject(1)); + int errorCode = RdbStepResultSetGetRowTest::store->Insert(rowId, "test", valuesBucket); + EXPECT_EQ(E_OK, errorCode); + EXPECT_EQ(1, rowId); + + std::unique_ptr resultSet = RdbStepResultSetGetRowTest::store->QueryByStep("SELECT * FROM test"); + EXPECT_NE(resultSet, nullptr); + + EXPECT_EQ(E_OK, resultSet->GoToFirstRow()); + + int iRet = E_ERROR; + RowEntity rowEntity; + iRet = resultSet->GetRow(rowEntity); + EXPECT_EQ(E_OK, iRet); + + int idValue = rowEntity.Get("id"); + EXPECT_EQ(1, idValue); + + int idValueByIndex = rowEntity.Get(0); + EXPECT_EQ(1, idValueByIndex); + + resultSet->Close(); +} + +/* * + * @tc.name: RdbStore_StepResultSet_GetRow_002 + * @tc.desc: test StepResultSet GetRow + * @tc.type: FUNC + * @tc.require: AR000FKD4F + */ +HWTEST_F(RdbStepResultSetGetRowTest, RdbStore_StepResultSet_GetRow_002, TestSize.Level1) +{ + ValuesBucket valuesBucket; + valuesBucket.PutNull("data1"); + valuesBucket.PutNull("data2"); + valuesBucket.PutNull("data3"); + valuesBucket.PutNull("data4"); + valuesBucket.PutNull("data5"); + int64_t rowId; + int errorCode = RdbStepResultSetGetRowTest::store->Insert(rowId, "test", valuesBucket); + EXPECT_EQ(E_OK, errorCode); + EXPECT_EQ(1, rowId); + + std::unique_ptr resultSet = RdbStepResultSetGetRowTest::store->QueryByStep("SELECT * FROM test"); + EXPECT_NE(resultSet, nullptr); + + EXPECT_EQ(E_OK, resultSet->GoToFirstRow()); + + int iRet = E_ERROR; + RowEntity rowEntity; + iRet = resultSet->GetRow(rowEntity); + EXPECT_EQ(E_OK, iRet); + + int idValue = rowEntity.Get("id"); + EXPECT_EQ(1, idValue); + + int idValueByIndex = rowEntity.Get(0); + EXPECT_EQ(1, idValueByIndex); + + resultSet->Close(); +} + +/* * + * @tc.name: RdbStore_StepResultSet_GetRow_003 + * @tc.desc: test StepResultSet GetRow + * @tc.type: FUNC + * @tc.require: AR000FKD4F + */ +HWTEST_F(RdbStepResultSetGetRowTest, RdbStore_StepResultSet_GetRow_003, TestSize.Level1) +{ + ValuesBucket valuesBucket; + valuesBucket.PutString("data1", "olleh"); + valuesBucket.PutInt("data2", 20); + valuesBucket.PutDouble("data3", 2.0); + valuesBucket.PutBlob("data4", { 4, 3, 2, 1 }); + valuesBucket.PutBool("data5", true); + int64_t rowId; + int errorCode = RdbStepResultSetGetRowTest::store->Insert(rowId, "test", valuesBucket); + EXPECT_EQ(E_OK, errorCode); + EXPECT_EQ(1, rowId); + + std::unique_ptr resultSet = RdbStepResultSetGetRowTest::store->QueryByStep("SELECT * FROM test"); + EXPECT_NE(resultSet, nullptr); + + EXPECT_EQ(E_OK, resultSet->GoToFirstRow()); + + int iRet = E_ERROR; + RowEntity rowEntity; + iRet = resultSet->GetRow(rowEntity); + EXPECT_EQ(E_OK, iRet); + + int idValue = rowEntity.Get("id"); + std::string data1Value = rowEntity.Get("data1"); + int data2Value = rowEntity.Get("data2"); + double data3Value = rowEntity.Get("data3"); + std::vector data4Value = rowEntity.Get("data4"); + int data5Value = rowEntity.Get("data5"); + EXPECT_EQ(1, idValue); + EXPECT_EQ("olleh", data1Value); + EXPECT_EQ(20, data2Value); + EXPECT_EQ(2.0, data3Value); + EXPECT_EQ(1, data4Value[3]); + EXPECT_EQ(1, data5Value); + + int idValueByIndex = rowEntity.Get(0); + std::string data1ValueByIndex = rowEntity.Get(1); + int data2ValueByIndex = rowEntity.Get(2); + double data3ValueByIndex = rowEntity.Get(3); + std::vector data4ValueByIndex = rowEntity.Get(4); + int data5ValueByIndex = rowEntity.Get(5); + EXPECT_EQ(1, idValueByIndex); + EXPECT_EQ("olleh", data1ValueByIndex); + EXPECT_EQ(20, data2ValueByIndex); + EXPECT_EQ(2.0, data3ValueByIndex); + EXPECT_EQ(1, data4ValueByIndex[3]); + EXPECT_EQ(1, data5ValueByIndex); + + resultSet->Close(); +} + +/* * + * @tc.name: RdbStore_StepResultSet_GetRow_004 + * @tc.desc: test StepResultSet GetRow + * @tc.type: FUNC + * @tc.require: AR000FKD4F + */ +HWTEST_F(RdbStepResultSetGetRowTest, RdbStore_StepResultSet_GetRow_004, TestSize.Level1) +{ + ValuesBucket valuesBucket; + valuesBucket.PutString("data1", ""); + valuesBucket.PutInt("data2", 10); + valuesBucket.PutDouble("data3", 1.0); + valuesBucket.PutBlob("data4", { 1, 2, 3, 4 }); + valuesBucket.PutBool("data5", true); + int64_t rowId; + int errorCode = RdbStepResultSetGetRowTest::store->Insert(rowId, "test", valuesBucket); + EXPECT_EQ(E_OK, errorCode); + EXPECT_EQ(1, rowId); + + std::unique_ptr resultSet = + RdbStepResultSetGetRowTest::store->QueryByStep("SELECT data1, data2 FROM test"); + EXPECT_NE(resultSet, nullptr); + + EXPECT_EQ(E_OK, resultSet->GoToFirstRow()); + + int iRet = E_ERROR; + RowEntity rowEntity; + iRet = resultSet->GetRow(rowEntity); + EXPECT_EQ(E_OK, iRet); + + std::string data1Value = rowEntity.Get("data1"); + EXPECT_EQ("", data1Value); + + std::string data1ValueByIndex = rowEntity.Get(0); + EXPECT_EQ("", data1ValueByIndex); + + resultSet->Close(); +} \ No newline at end of file diff --git a/relational_store/test/native/rdb/unittest/rdb_step_result_set_test.cpp b/relational_store/test/native/rdb/unittest/rdb_step_result_set_test.cpp index 22ee3381..3cd6e7b0 100644 --- a/relational_store/test/native/rdb/unittest/rdb_step_result_set_test.cpp +++ b/relational_store/test/native/rdb/unittest/rdb_step_result_set_test.cpp @@ -13,8 +13,10 @@ * limitations under the License. */ +#include #include #include + #include "common.h" #include "logger.h" #include "rdb_errno.h" @@ -35,14 +37,10 @@ public: static const std::string DATABASE_NAME; static std::shared_ptr store; - static const int E_SQLITE_ERROR; - static const int E_INVALID_COLUMN_TYPE; }; const std::string RdbStepResultSetTest::DATABASE_NAME = RDB_TEST_PATH + "stepResultSet_test.db"; std::shared_ptr RdbStepResultSetTest::store = nullptr; -const int RdbStepResultSetTest::E_SQLITE_ERROR = -1; // errno SQLITE_ERROR -const int RdbStepResultSetTest::E_INVALID_COLUMN_TYPE = 1009; // errno SQLITE_NULL class RdbStepResultSetOpenCallback : public RdbOpenCallback { public: @@ -137,12 +135,13 @@ HWTEST_F(RdbStepResultSetTest, RdbStore_StepResultSet_001, TestSize.Level1) std::unique_ptr resultSet = store->QueryByStep("SELECT * FROM test"); EXPECT_NE(resultSet, nullptr); - bool bResultSet = false; + bool bResultSet = true; int iRet = resultSet->IsStarted(bResultSet); EXPECT_EQ(E_OK, iRet); EXPECT_EQ(bResultSet, false); EXPECT_EQ(resultSet->GoTo(1), E_OK); + bResultSet = false; iRet = resultSet->IsAtFirstRow(bResultSet); EXPECT_EQ(E_OK, iRet); EXPECT_EQ(bResultSet, true); @@ -216,17 +215,18 @@ HWTEST_F(RdbStepResultSetTest, RdbStore_StepResultSet_002, TestSize.Level1) resultSet->GetRowCount(count); EXPECT_EQ(3, count); - int position = -1; + int position = INT_MIN; int iRet = resultSet->GetRowIndex(position); EXPECT_EQ(E_OK, iRet); EXPECT_EQ(-1, position); - bool bResultSet = false; + bool bResultSet = true; resultSet->IsAtFirstRow(bResultSet); EXPECT_EQ(bResultSet, false); EXPECT_EQ(E_OK, resultSet->GoToRow(2)); + bResultSet = false; iRet = resultSet->IsAtLastRow(bResultSet); EXPECT_EQ(E_OK, iRet); EXPECT_EQ(true, bResultSet); @@ -239,14 +239,17 @@ HWTEST_F(RdbStepResultSetTest, RdbStore_StepResultSet_002, TestSize.Level1) EXPECT_EQ(E_OK, resultSet->GoToLastRow()); + bResultSet = false; iRet = resultSet->IsAtLastRow(bResultSet); EXPECT_EQ(E_OK, iRet); EXPECT_EQ(true, bResultSet); + bResultSet = false; iRet = resultSet->IsStarted(bResultSet); EXPECT_EQ(E_OK, iRet); EXPECT_EQ(bResultSet, true); + bResultSet = true; iRet = resultSet->IsEnded(bResultSet); EXPECT_EQ(E_OK, iRet); EXPECT_EQ(bResultSet, false); @@ -264,8 +267,8 @@ HWTEST_F(RdbStepResultSetTest, RdbStore_StepResultSet_003, TestSize.Level1) std::unique_ptr resultSet = store->QueryByStep("SELECT * FROM test"); EXPECT_NE(resultSet, nullptr); - int position = -1; - bool bResultSet = false; + int position = INT_MIN; + bool bResultSet = true; int iRet = resultSet->GetRowIndex(position); EXPECT_EQ(E_OK, iRet); EXPECT_EQ(-1, position); @@ -274,10 +277,12 @@ HWTEST_F(RdbStepResultSetTest, RdbStore_StepResultSet_003, TestSize.Level1) EXPECT_EQ(E_OK, iRet); EXPECT_EQ(bResultSet, false); + bResultSet = true; iRet = resultSet->IsAtFirstRow(bResultSet); EXPECT_EQ(E_OK, iRet); EXPECT_EQ(bResultSet, false); + bResultSet = true; iRet = resultSet->IsEnded(bResultSet); EXPECT_EQ(E_OK, iRet); EXPECT_EQ(bResultSet, false); @@ -290,14 +295,17 @@ HWTEST_F(RdbStepResultSetTest, RdbStore_StepResultSet_003, TestSize.Level1) EXPECT_EQ(E_OK, iRet); EXPECT_EQ(0, position); + bResultSet = false; iRet = resultSet->IsStarted(bResultSet); EXPECT_EQ(E_OK, iRet); EXPECT_EQ(bResultSet, true); + bResultSet = false; iRet = resultSet->IsAtFirstRow(bResultSet); EXPECT_EQ(E_OK, iRet); EXPECT_EQ(bResultSet, true); + bResultSet = true; iRet = resultSet->IsEnded(bResultSet); EXPECT_EQ(E_OK, iRet); EXPECT_EQ(bResultSet, false); @@ -314,14 +322,17 @@ HWTEST_F(RdbStepResultSetTest, RdbStore_StepResultSet_003, TestSize.Level1) EXPECT_EQ(E_OK, iRet); EXPECT_EQ(-1, position); + bResultSet = true; iRet = resultSet->IsStarted(bResultSet); EXPECT_EQ(E_OK, iRet); EXPECT_EQ(bResultSet, false); + bResultSet = true; iRet = resultSet->IsAtFirstRow(bResultSet); EXPECT_EQ(E_OK, iRet); EXPECT_EQ(bResultSet, false); + bResultSet = false; iRet = resultSet->IsEnded(bResultSet); EXPECT_EQ(E_OK, iRet); EXPECT_EQ(bResultSet, true); @@ -339,8 +350,8 @@ HWTEST_F(RdbStepResultSetTest, RdbStore_StepResultSet_004, TestSize.Level1) std::unique_ptr resultSet = store->QueryByStep("SELECT data1, data2, data3, data4 FROM test"); EXPECT_NE(resultSet, nullptr); - int position = -1; - bool bResultSet = false; + int position = INT_MIN; + bool bResultSet = true; int iRet = resultSet->GetRowIndex(position); EXPECT_EQ(E_OK, iRet); EXPECT_EQ(-1, position); @@ -349,6 +360,7 @@ HWTEST_F(RdbStepResultSetTest, RdbStore_StepResultSet_004, TestSize.Level1) EXPECT_EQ(E_OK, iRet); EXPECT_EQ(bResultSet, false); + bResultSet = true; iRet = resultSet->IsAtFirstRow(bResultSet); EXPECT_EQ(E_OK, iRet); EXPECT_EQ(bResultSet, false); @@ -359,10 +371,12 @@ HWTEST_F(RdbStepResultSetTest, RdbStore_StepResultSet_004, TestSize.Level1) EXPECT_EQ(E_OK, iRet); EXPECT_EQ(-1, position); + bResultSet = true; iRet = resultSet->IsStarted(bResultSet); EXPECT_EQ(E_OK, iRet); EXPECT_EQ(bResultSet, false); + bResultSet = true; iRet = resultSet->IsAtFirstRow(bResultSet); EXPECT_EQ(E_OK, iRet); EXPECT_EQ(bResultSet, false); @@ -382,7 +396,7 @@ HWTEST_F(RdbStepResultSetTest, RdbStore_StepResultSet_005, TestSize.Level1) EXPECT_EQ(E_OK, resultSet->GoToFirstRow()); - int position = -1; + int position = INT_MIN; bool bResultSet = false; int iRet = resultSet->GetRowIndex(position); EXPECT_EQ(E_OK, iRet); @@ -392,6 +406,7 @@ HWTEST_F(RdbStepResultSetTest, RdbStore_StepResultSet_005, TestSize.Level1) EXPECT_EQ(E_OK, iRet); EXPECT_EQ(bResultSet, true); + bResultSet = false; iRet = resultSet->IsStarted(bResultSet); EXPECT_EQ(E_OK, iRet); EXPECT_EQ(bResultSet, true); @@ -401,10 +416,12 @@ HWTEST_F(RdbStepResultSetTest, RdbStore_StepResultSet_005, TestSize.Level1) EXPECT_EQ(E_OK, iRet); EXPECT_EQ(0, position); + bResultSet = false; iRet = resultSet->IsAtFirstRow(bResultSet); EXPECT_EQ(E_OK, iRet); EXPECT_EQ(bResultSet, true); + bResultSet = false; iRet = resultSet->IsStarted(bResultSet); EXPECT_EQ(E_OK, iRet); EXPECT_EQ(bResultSet, true); @@ -412,10 +429,12 @@ HWTEST_F(RdbStepResultSetTest, RdbStore_StepResultSet_005, TestSize.Level1) EXPECT_EQ(E_OK, resultSet->GoToNextRow()); EXPECT_EQ(E_OK, resultSet->GoToFirstRow()); + bResultSet = false; iRet = resultSet->IsAtFirstRow(bResultSet); EXPECT_EQ(E_OK, iRet); EXPECT_EQ(bResultSet, true); + bResultSet = false; iRet = resultSet->IsStarted(bResultSet); EXPECT_EQ(E_OK, iRet); EXPECT_EQ(bResultSet, true); @@ -435,8 +454,8 @@ HWTEST_F(RdbStepResultSetTest, RdbStore_StepResultSet_006, TestSize.Level1) EXPECT_NE(E_OK, resultSet->GoToFirstRow()); - int position = -1; - bool bResultSet = false; + int position = INT_MIN; + bool bResultSet = true; int iRet = resultSet->GetRowIndex(position); EXPECT_EQ(E_OK, iRet); EXPECT_EQ(-1, position); @@ -445,6 +464,7 @@ HWTEST_F(RdbStepResultSetTest, RdbStore_StepResultSet_006, TestSize.Level1) EXPECT_EQ(E_OK, iRet); EXPECT_EQ(bResultSet, false); + bResultSet = true; iRet = resultSet->IsStarted(bResultSet); EXPECT_EQ(E_OK, iRet); EXPECT_EQ(bResultSet, false); @@ -452,10 +472,12 @@ HWTEST_F(RdbStepResultSetTest, RdbStore_StepResultSet_006, TestSize.Level1) EXPECT_NE(E_OK, resultSet->GoToNextRow()); EXPECT_NE(E_OK, resultSet->GoToFirstRow()); + bResultSet = true; iRet = resultSet->IsAtFirstRow(bResultSet); EXPECT_EQ(E_OK, iRet); EXPECT_EQ(bResultSet, false); + bResultSet = true; iRet = resultSet->IsStarted(bResultSet); EXPECT_EQ(E_OK, iRet); EXPECT_EQ(bResultSet, false); @@ -476,8 +498,8 @@ HWTEST_F(RdbStepResultSetTest, RdbStore_StepResultSet_007, TestSize.Level1) int moveTimes = 0; EXPECT_EQ(E_OK, resultSet->GoToFirstRow()); moveTimes++; - int position = -1; - bool bResultSet = false; + int position = INT_MIN; + bool bResultSet = true; int iRet = resultSet->GetRowIndex(position); EXPECT_EQ(E_OK, iRet); EXPECT_EQ(0, position); @@ -493,6 +515,7 @@ HWTEST_F(RdbStepResultSetTest, RdbStore_StepResultSet_007, TestSize.Level1) EXPECT_EQ(E_OK, iRet); EXPECT_EQ(-1, position); + bResultSet = false; iRet = resultSet->IsEnded(bResultSet); EXPECT_EQ(E_OK, iRet); EXPECT_EQ(bResultSet, true); @@ -513,7 +536,7 @@ HWTEST_F(RdbStepResultSetTest, RdbStore_StepResultSet_008, TestSize.Level1) EXPECT_NE(E_OK, resultSet->GoToFirstRow()); moveTimes++; - int position = -1; + int position = INT_MIN; bool bResultSet = false; int iRet = resultSet->GetRowIndex(position); EXPECT_EQ(E_OK, iRet); @@ -530,6 +553,7 @@ HWTEST_F(RdbStepResultSetTest, RdbStore_StepResultSet_008, TestSize.Level1) EXPECT_EQ(E_OK, iRet); EXPECT_EQ(-1, position); + bResultSet = false; iRet = resultSet->IsEnded(bResultSet); EXPECT_EQ(E_OK, iRet); EXPECT_EQ(bResultSet, true); @@ -888,6 +912,7 @@ HWTEST_F(RdbStepResultSetTest, RdbStore_StepResultSet_016, TestSize.Level1) EXPECT_EQ(E_OK, iRet); EXPECT_EQ(bResultSet, true); + bResultSet = false; iRet = resultSet->IsStarted(bResultSet); EXPECT_EQ(E_OK, iRet); EXPECT_EQ(bResultSet, true); @@ -915,7 +940,7 @@ HWTEST_F(RdbStepResultSetTest, testGetRowCount003, TestSize.Level1) std::unique_ptr resultSet = store->QueryByStep("SELECT * FROM test"); EXPECT_NE(resultSet, nullptr); - bool bResultSet = false; + bool bResultSet = true; int iRet = resultSet->IsStarted(bResultSet); EXPECT_EQ(E_OK, iRet); EXPECT_EQ(bResultSet, false); @@ -926,6 +951,7 @@ HWTEST_F(RdbStepResultSetTest, testGetRowCount003, TestSize.Level1) EXPECT_EQ(3, count); EXPECT_EQ(E_OK, resultSet->GoToNextRow()); + bResultSet = false; iRet = resultSet->IsAtFirstRow(bResultSet); EXPECT_EQ(E_OK, iRet); EXPECT_EQ(bResultSet, true); @@ -963,7 +989,7 @@ HWTEST_F(RdbStepResultSetTest, testGetRowCount003, TestSize.Level1) EXPECT_EQ(3, count); EXPECT_EQ(E_OK, resultSet->GoToNextRow()); - int position = -1; + int position = INT_MIN; iRet = resultSet->GetRowIndex(position); EXPECT_EQ(E_OK, iRet); EXPECT_EQ(1, position); @@ -1005,12 +1031,13 @@ HWTEST_F(RdbStepResultSetTest, testGetRowCount004, TestSize.Level1) std::unique_ptr resultSet = store->QueryByStep("SELECT data1, data2, data3, data4 FROM test"); EXPECT_NE(resultSet, nullptr); - bool bResultSet = false; + bool bResultSet = true; int iRet = resultSet->IsStarted(bResultSet); EXPECT_EQ(E_OK, iRet); EXPECT_EQ(bResultSet, false); EXPECT_EQ(E_OK, resultSet->GoToNextRow()); + bResultSet = false; iRet = resultSet->IsAtFirstRow(bResultSet); EXPECT_EQ(E_OK, iRet); EXPECT_EQ(bResultSet, true); @@ -1050,7 +1077,7 @@ HWTEST_F(RdbStepResultSetTest, testGetRowCount004, TestSize.Level1) EXPECT_EQ(E_OK, resultSet->GoToNextRow()); - int position = -1; + int position = INT_MIN; iRet = resultSet->GetRowIndex(position); EXPECT_EQ(E_OK, iRet); EXPECT_EQ(1, position); @@ -1093,17 +1120,18 @@ HWTEST_F(RdbStepResultSetTest, testGoToRow005, TestSize.Level1) std::unique_ptr resultSet = store->QueryByStep("SELECT data1, data2, data3, data4 FROM test"); EXPECT_NE(resultSet, nullptr); - bool bResultSet = false; + bool bResultSet = true; int iRet = resultSet->IsStarted(bResultSet); EXPECT_EQ(E_OK, iRet); EXPECT_EQ(bResultSet, false); EXPECT_EQ(E_OK, resultSet->GoToNextRow()); + bResultSet = false; iRet = resultSet->IsAtFirstRow(bResultSet); EXPECT_EQ(E_OK, iRet); EXPECT_EQ(bResultSet, true); - int position = -1; + int position = INT_MIN; iRet = resultSet->GetRowIndex(position); EXPECT_EQ(E_OK, iRet); EXPECT_EQ(0, position); @@ -1167,7 +1195,7 @@ HWTEST_F(RdbStepResultSetTest, testGo006, TestSize.Level1) GenerateDefaultTable(); std::unique_ptr resultSet = store->QueryByStep("SELECT * FROM test"); EXPECT_NE(resultSet, nullptr); - int position = -1; + int position = INT_MIN; int iRet = resultSet->GetRowIndex(position); EXPECT_EQ(E_OK, iRet); EXPECT_EQ(-1, position); @@ -1252,13 +1280,14 @@ HWTEST_F(RdbStepResultSetTest, testGoToPrevious007, TestSize.Level1) EXPECT_EQ(E_OK, iRet); EXPECT_EQ(3, count); - bool bResultSet = false; + bool bResultSet = true; iRet = resultSet->IsStarted(bResultSet); EXPECT_EQ(E_OK, iRet); EXPECT_EQ(bResultSet, false); EXPECT_EQ(E_OK, resultSet->GoToFirstRow()); + bResultSet = false; iRet = resultSet->IsAtFirstRow(bResultSet); EXPECT_EQ(E_OK, iRet); EXPECT_EQ(bResultSet, true); @@ -1295,11 +1324,12 @@ HWTEST_F(RdbStepResultSetTest, testGoToPrevious007, TestSize.Level1) int ret = resultSet->GoToPreviousRow(); EXPECT_NE(E_OK, ret); - int position = -1; + int position = INT_MIN; iRet = resultSet->GetRowIndex(position); EXPECT_EQ(E_OK, iRet); EXPECT_EQ(-1, position); + bResultSet = true; iRet = resultSet->IsStarted(bResultSet); EXPECT_EQ(E_OK, iRet); EXPECT_EQ(bResultSet, false); @@ -1323,6 +1353,7 @@ HWTEST_F(RdbStepResultSetTest, testGoToPrevious007, TestSize.Level1) EXPECT_EQ(E_OK, resultSet->GoToLastRow()); + bResultSet = false; iRet = resultSet->IsAtLastRow(bResultSet); EXPECT_EQ(E_OK, iRet); EXPECT_EQ(true, bResultSet); @@ -1339,6 +1370,7 @@ HWTEST_F(RdbStepResultSetTest, testGoToPrevious007, TestSize.Level1) EXPECT_EQ(E_OK, iRet); EXPECT_EQ(-1, position); + bResultSet = false; iRet = resultSet->IsEnded(bResultSet); EXPECT_EQ(E_OK, iRet); EXPECT_EQ(bResultSet, true); @@ -1356,13 +1388,14 @@ HWTEST_F(RdbStepResultSetTest, testSqlStep008, TestSize.Level1) std::unique_ptr resultSet = store->QueryByStep("SELECT data1, data2, data3, data4 FROM test"); EXPECT_NE(resultSet, nullptr); - bool bResultSet = false; + bool bResultSet = true; int iRet = resultSet->IsStarted(bResultSet); EXPECT_EQ(E_OK, iRet); EXPECT_EQ(bResultSet, false); EXPECT_EQ(E_OK, resultSet->GoTo(1)); + bResultSet = false; iRet = resultSet->IsAtFirstRow(bResultSet); EXPECT_EQ(E_OK, iRet); EXPECT_EQ(bResultSet, true); @@ -1387,7 +1420,7 @@ HWTEST_F(RdbStepResultSetTest, testSqlStep008, TestSize.Level1) EXPECT_EQ(E_OK, resultSet->GoToFirstRow()); EXPECT_EQ(E_OK, resultSet->GoToNextRow()); - int position = -1; + int position = INT_MIN; iRet = resultSet->GetRowIndex(position); EXPECT_EQ(E_OK, iRet); EXPECT_EQ(1, position); @@ -1435,18 +1468,19 @@ HWTEST_F(RdbStepResultSetTest, testSqlStep009, TestSize.Level1) EXPECT_EQ(E_OK, iRet); EXPECT_EQ(3, count); - int position = -1; + int position = INT_MIN; iRet = resultSet->GetRowIndex(position); EXPECT_EQ(E_OK, iRet); EXPECT_EQ(-1, position); - bool bResultSet = false; + bool bResultSet = true; iRet = resultSet->IsAtFirstRow(bResultSet); EXPECT_EQ(E_OK, iRet); EXPECT_EQ(bResultSet, false); EXPECT_EQ(E_OK, resultSet->GoToRow(2)); + bResultSet = false; iRet = resultSet->IsAtLastRow(bResultSet); EXPECT_EQ(E_OK, iRet); EXPECT_EQ(true, bResultSet); @@ -1459,18 +1493,22 @@ HWTEST_F(RdbStepResultSetTest, testSqlStep009, TestSize.Level1) EXPECT_EQ(E_OK, resultSet->GoToLastRow()); + bResultSet = false; iRet = resultSet->IsAtLastRow(bResultSet); EXPECT_EQ(E_OK, iRet); EXPECT_EQ(true, bResultSet); + bResultSet = false; iRet = resultSet->IsAtLastRow(bResultSet); EXPECT_EQ(E_OK, iRet); EXPECT_EQ(true, bResultSet); + bResultSet = false; iRet = resultSet->IsStarted(bResultSet); EXPECT_EQ(E_OK, iRet); EXPECT_EQ(bResultSet, true); + bResultSet = true; iRet = resultSet->IsEnded(bResultSet); EXPECT_EQ(E_OK, iRet); EXPECT_EQ(bResultSet, false); @@ -1488,19 +1526,21 @@ HWTEST_F(RdbStepResultSetTest, testSqlStep010, TestSize.Level1) std::unique_ptr resultSet = store->QueryByStep("SELECT data1, data2, data3, data4 FROM test"); EXPECT_NE(resultSet, nullptr); - int position = -1; + int position = INT_MIN; int iRet = resultSet->GetRowIndex(position); EXPECT_EQ(E_OK, iRet); EXPECT_EQ(-1, position); - bool bResultSet = false; + bool bResultSet = true; iRet = resultSet->IsStarted(bResultSet); EXPECT_EQ(E_OK, iRet); EXPECT_EQ(bResultSet, false); + bResultSet = true; iRet = resultSet->IsAtFirstRow(bResultSet); EXPECT_EQ(E_OK, iRet); EXPECT_EQ(bResultSet, false); + bResultSet = true; iRet = resultSet->IsEnded(bResultSet); EXPECT_EQ(E_OK, iRet); EXPECT_EQ(bResultSet, false); @@ -1513,14 +1553,17 @@ HWTEST_F(RdbStepResultSetTest, testSqlStep010, TestSize.Level1) EXPECT_EQ(E_OK, iRet); EXPECT_EQ(0, position); + bResultSet = false; iRet = resultSet->IsStarted(bResultSet); EXPECT_EQ(E_OK, iRet); EXPECT_EQ(bResultSet, true); + bResultSet = false; iRet = resultSet->IsAtFirstRow(bResultSet); EXPECT_EQ(E_OK, iRet); EXPECT_EQ(bResultSet, true); + bResultSet = true; iRet = resultSet->IsEnded(bResultSet); EXPECT_EQ(E_OK, iRet); EXPECT_EQ(bResultSet, false); @@ -1533,14 +1576,17 @@ HWTEST_F(RdbStepResultSetTest, testSqlStep010, TestSize.Level1) EXPECT_EQ(E_OK, iRet); EXPECT_EQ(-1, position); + bResultSet = true; iRet = resultSet->IsStarted(bResultSet); EXPECT_EQ(E_OK, iRet); EXPECT_EQ(bResultSet, false); + bResultSet = true; iRet = resultSet->IsAtFirstRow(bResultSet); EXPECT_EQ(E_OK, iRet); EXPECT_EQ(bResultSet, false); + bResultSet = false; iRet = resultSet->IsEnded(bResultSet); EXPECT_EQ(E_OK, iRet); EXPECT_EQ(bResultSet, true); diff --git a/relational_store/test/native/rdb/unittest/rdb_store_rekey_test.cpp b/relational_store/test/native/rdb/unittest/rdb_store_rekey_test.cpp index cca265c4..ab96934f 100644 --- a/relational_store/test/native/rdb/unittest/rdb_store_rekey_test.cpp +++ b/relational_store/test/native/rdb/unittest/rdb_store_rekey_test.cpp @@ -35,11 +35,11 @@ public: void TearDown() override; static std::string RemoveSuffix(const std::string &name); - std::chrono::system_clock::time_point GetKeyFileDate(const std::string &dbName); - bool ChangeKeyFileDate(const std::string &dbName, int rep); - RdbStoreConfig GetRdbConfig(const std::string &name); - void InsertData(std::shared_ptr &store); - void CheckQueryData(std::shared_ptr &store); + static std::chrono::system_clock::time_point GetKeyFileDate(const std::string &dbName); + static bool ChangeKeyFileDate(const std::string &dbName, int rep); + static RdbStoreConfig GetRdbConfig(const std::string &name); + static void InsertData(std::shared_ptr &store); + static void CheckQueryData(std::shared_ptr &store); static const std::string encryptedDatabaseName; static const std::string encryptedDatabasePath; @@ -286,4 +286,42 @@ HWTEST_F(RdbRekeyTest, Rdb_Rekey_03, TestSize.Level1) RdbStoreConfig config = GetRdbConfig(encryptedDatabasePath); std::shared_ptr store = RdbHelper::GetRdbStore(config, 1, helper, errCode); ASSERT_EQ(store, nullptr); +} + +/** +* @tc.name: Rdb_Rekey_Test_004 +* @tc.desc: try to open store and modify create date to a future time. +* @tc.type: FUNC +*/ +HWTEST_F(RdbRekeyTest, Rdb_Rekey_04, TestSize.Level1) +{ + std::string keyPath = encryptedDatabaseKeyDir + RemoveSuffix(encryptedDatabaseName) + ".pub_key"; + std::string newKeyPath = encryptedDatabaseKeyDir + RemoveSuffix(encryptedDatabaseName) + ".pub_key.new"; + + bool isFileExists = OHOS::FileExists(keyPath); + ASSERT_TRUE(isFileExists); + + auto keyFileDate = GetKeyFileDate(encryptedDatabaseName); + + bool isFileDateChanged = ChangeKeyFileDate(encryptedDatabaseName, -RdbRekeyTest::HOURS_EXPIRED); + ASSERT_TRUE(isFileDateChanged); + + auto changedDate = GetKeyFileDate(encryptedDatabaseName); + ASSERT_GT(changedDate, keyFileDate); + + RdbStoreConfig config = GetRdbConfig(RdbRekeyTest::encryptedDatabasePath); + RekeyTestOpenCallback helper; + int errCode; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + ASSERT_NE(store, nullptr); + + isFileExists = OHOS::FileExists(keyPath); + ASSERT_TRUE(isFileExists); + isFileExists = OHOS::FileExists(newKeyPath); + ASSERT_FALSE(isFileExists); + + keyFileDate = GetKeyFileDate(encryptedDatabaseName); + ASSERT_EQ(changedDate, keyFileDate); + + CheckQueryData(store); } \ No newline at end of file diff --git a/relational_store/test/native/rdb/unittest/rdb_transaction_test.cpp b/relational_store/test/native/rdb/unittest/rdb_transaction_test.cpp index 665328fa..bda1219a 100644 --- a/relational_store/test/native/rdb/unittest/rdb_transaction_test.cpp +++ b/relational_store/test/native/rdb/unittest/rdb_transaction_test.cpp @@ -15,6 +15,7 @@ #include +#include #include #include "common.h" @@ -35,12 +36,10 @@ public: static const std::string DATABASE_NAME; static std::shared_ptr store; - static const int E_SQLITE_ERROR; // errno SQLITE_ERROR }; const std::string RdbTransactionTest::DATABASE_NAME = RDB_TEST_PATH + "transaction_test.db"; std::shared_ptr RdbTransactionTest::store = nullptr; -const int RdbTransactionTest::E_SQLITE_ERROR = -1; // errno SQLITE_ERROR class TransactionTestOpenCallback : public RdbOpenCallback { public: @@ -675,7 +674,7 @@ HWTEST_F(RdbTransactionTest, RdbStore_BatchInsert_003, TestSize.Level1) valuesBuckets.push_back(std::move(values)); } - number = -1; + number = INT_MIN; error = store->BatchInsert(number, "test", valuesBuckets); EXPECT_EQ(E_OK, error); EXPECT_EQ(-1, number); diff --git a/relational_store/test/native/rdb/unittest/rdb_value_bucket_test.cpp b/relational_store/test/native/rdb/unittest/rdb_value_bucket_test.cpp index b7b5ff48..039c070c 100644 --- a/relational_store/test/native/rdb/unittest/rdb_value_bucket_test.cpp +++ b/relational_store/test/native/rdb/unittest/rdb_value_bucket_test.cpp @@ -22,8 +22,8 @@ #include "parcel.h" #include "value_object.h" #include "values_bucket.h" +#include "sqlite_global_config.h" #include "itypes_util.h" - using namespace testing::ext; using namespace OHOS; using namespace OHOS::NativeRdb; diff --git a/relational_store/test/native/rdb_data_share_adapter/unittest/rdb_data_share_adapter_test.cpp b/relational_store/test/native/rdb_data_share_adapter/unittest/rdb_data_share_adapter_test.cpp index 21eb06ca..96fda84d 100644 --- a/relational_store/test/native/rdb_data_share_adapter/unittest/rdb_data_share_adapter_test.cpp +++ b/relational_store/test/native/rdb_data_share_adapter/unittest/rdb_data_share_adapter_test.cpp @@ -44,17 +44,11 @@ public: static const std::string DATABASE_NAME; static std::shared_ptr store; - static const int E_SQLITE_ERROR; - static const int E_INVALID_COLUMN_TYPE; - static const size_t DEFAULT_BLOCK_SIZE; static const std::string RDB_ADAPTER_TEST_PATH; }; const std::string RdbDataShareAdapterTest::RDB_ADAPTER_TEST_PATH = "/data/test/"; const std::string RdbDataShareAdapterTest::DATABASE_NAME = RDB_ADAPTER_TEST_PATH + "rdbDataShareAdapter_test.db"; -const int RdbDataShareAdapterTest::E_SQLITE_ERROR = -1; // errno SQLITE_ERROR -const int RdbDataShareAdapterTest::E_INVALID_COLUMN_TYPE = 1009; // errno SQLITE_NULL -const size_t RdbDataShareAdapterTest::DEFAULT_BLOCK_SIZE = 2 * 1024 * 1024; std::shared_ptr RdbDataShareAdapterTest::store = nullptr; class RdbStepSharedResultSetOpenCallback : public RdbOpenCallback { -- Gitee From cdeb1b974135c37e36391c99927ec406c373ac46 Mon Sep 17 00:00:00 2001 From: Sven Wang Date: Wed, 19 Apr 2023 16:53:44 +0800 Subject: [PATCH 18/44] update Signed-off-by: Sven Wang --- .../framework/include/cloud/asset_loader.h | 4 ++-- .../framework/include/cloud/cloud_db.h | 2 +- .../framework/include/cloud/schema_meta.h | 5 +++++ .../distributeddataservice/framework/include/store/cursor.h | 2 -- 4 files changed, 8 insertions(+), 5 deletions(-) diff --git a/datamgr_service/services/distributeddataservice/framework/include/cloud/asset_loader.h b/datamgr_service/services/distributeddataservice/framework/include/cloud/asset_loader.h index b4cd0d9f..ec3b9a80 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/cloud/asset_loader.h +++ b/datamgr_service/services/distributeddataservice/framework/include/cloud/asset_loader.h @@ -20,8 +20,8 @@ namespace OHOS::DistributedData { class AssetLoader { public: virtual ~AssetLoader() = 0; - virtual int32_t Upload(const std::vector &asset) = 0; - virtual int32_t Download(std::vector &asset) = 0; + virtual int32_t Upload(const std::vector &assets) = 0; + virtual int32_t Download(std::vector &assets) = 0; }; } // namespace OHOS::DistributedData #endif // OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_CLOUD_ASSET_LOADER_H diff --git a/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_db.h b/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_db.h index 586abb1e..5b968212 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_db.h +++ b/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_db.h @@ -26,7 +26,7 @@ public: virtual int32_t BatchUpdate(const std::string &table, VBuckets &&values, const VBuckets &extends) = 0; virtual int32_t Delete(const std::string &table, const VBucket &extend) = 0; virtual int32_t BatchDelete(const std::string &table, const VBuckets &extends) = 0; - virtual std::shared_ptr Query(const std::string &table, const VBuckets &extends) = 0; + virtual std::shared_ptr Query(const std::string &table, const VBucket &extend) = 0; virtual int32_t Lock() = 0; virtual int32_t Unlock() = 0; virtual int32_t Flush() = 0; diff --git a/datamgr_service/services/distributeddataservice/framework/include/cloud/schema_meta.h b/datamgr_service/services/distributeddataservice/framework/include/cloud/schema_meta.h index 4ae4a169..188a0132 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/cloud/schema_meta.h +++ b/datamgr_service/services/distributeddataservice/framework/include/cloud/schema_meta.h @@ -19,6 +19,11 @@ namespace OHOS::DistributedData { class API_EXPORT SchemaMeta final : public Serializable { public: + static constexpr const char *DELETE_FIELD = "#_deleted"; + static constexpr const char *GID_FIELD = "#_gid"; + static constexpr const char *CREATE_FIELD = "#_createTime"; + static constexpr const char *MODIFY_FIELD = "#_modifyTime"; + static constexpr const char *CURSOR_FIELD = "#_cursor"; struct API_EXPORT Field final : public Serializable { std::string colName; std::string alias; diff --git a/datamgr_service/services/distributeddataservice/framework/include/store/cursor.h b/datamgr_service/services/distributeddataservice/framework/include/store/cursor.h index 2ebf8a3e..e588c5fd 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/store/cursor.h +++ b/datamgr_service/services/distributeddataservice/framework/include/store/cursor.h @@ -25,8 +25,6 @@ class Cursor { public: virtual ~Cursor() = default; - virtual std::string NextCursorTag() const = 0; - virtual int32_t GetColumnNames(std::vector &names) const = 0; virtual int32_t GetColumnName(int32_t col, std::string &name) const = 0; -- Gitee From 8a0a135673a0b0e8e27087a545810e5a70cfcf4f Mon Sep 17 00:00:00 2001 From: htt1997 Date: Wed, 19 Apr 2023 20:48:33 +0800 Subject: [PATCH 19/44] update Signed-off-by: htt1997 --- .../framework/cloud/cloud_event.cpp | 18 ++- .../framework/cloud/cloud_info.cpp | 7 +- .../framework/include/cloud/cloud_event.h | 13 +- .../framework/include/cloud/cloud_info.h | 1 + .../service/cloud/cloud_service_impl.cpp | 66 +++++--- .../service/cloud/cloud_service_impl.h | 1 + .../data_share/data_share_service_stub.cpp | 50 +++--- .../service/object/object_service_stub.cpp | 53 ++++--- .../service/rdb/rdb_service_impl.cpp | 7 + .../service/rdb/rdb_service_impl.h | 2 + .../service/rdb/rdb_service_stub.cpp | 146 ++++++++++++------ .../service/rdb/rdb_service_stub.h | 5 +- .../js/napi/rdb/src/napi_rdb_store_helper.cpp | 1 + .../native/rdb/include/rdb_service_proxy.h | 1 + .../native/rdb/include/rdb_types_util.h | 5 + .../native/rdb/src/rdb_service_proxy.cpp | 11 ++ .../native/rdb/src/rdb_store_manager.cpp | 1 + .../native/rdb/src/rdb_types_util.cpp | 9 ++ .../inner_api/rdb/include/rdb_service.h | 3 + 19 files changed, 282 insertions(+), 118 deletions(-) diff --git a/datamgr_service/services/distributeddataservice/framework/cloud/cloud_event.cpp b/datamgr_service/services/distributeddataservice/framework/cloud/cloud_event.cpp index 66e58e6d..7ab8cbe7 100644 --- a/datamgr_service/services/distributeddataservice/framework/cloud/cloud_event.cpp +++ b/datamgr_service/services/distributeddataservice/framework/cloud/cloud_event.cpp @@ -16,18 +16,28 @@ #include "cloud/cloud_event.h" namespace OHOS::DistributedData { -CloudEvent::CloudEvent(int32_t evtId, int32_t user) - : Event(evtId), user_(user) +CloudEvent::CloudEvent(int32_t evtId, uint32_t tokenId, std::string storeName, std::string bundleName) + : Event(evtId), tokenId_(tokenId), storeName_(storeName), bundleName_(bundleName) { } -int32_t CloudEvent::GetUser() const +//int32_t CloudEvent::GetUser() const +//{ +// return user_; +//} + +std::string CloudEvent::GetBundleName() const { - return user_; + return bundleName_; } bool CloudEvent::Equals(const Event &event) const { return false; } + +uint32_t CloudEvent::GetTokenId() const +{ + return tokenId_; +} } \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/framework/cloud/cloud_info.cpp b/datamgr_service/services/distributeddataservice/framework/cloud/cloud_info.cpp index 4d022a2f..e8d83c18 100644 --- a/datamgr_service/services/distributeddataservice/framework/cloud/cloud_info.cpp +++ b/datamgr_service/services/distributeddataservice/framework/cloud/cloud_info.cpp @@ -72,6 +72,11 @@ std::map CloudInfo::GetSchemaKey() const return keys; } +std::string CloudInfo::GetSchemaKey(std::string bundleName) const +{ + return GetKey(SCHEMA_PREFIX, { std::to_string(user), id, bundleName }); +} + bool CloudInfo::IsValid() const { return !id.empty(); @@ -90,7 +95,7 @@ bool CloudInfo::IsExist(const std::string &bundleName) const void CloudInfo::DelApp(const std::string &bundleName) { for (auto it = apps.begin(); it != apps.end();) { - if ((*it).bundleName == bundleName) { + if (it->bundleName == bundleName) { it = apps.erase(it); break; } diff --git a/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_event.h b/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_event.h index 2ef233a7..ebb1004b 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_event.h +++ b/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_event.h @@ -24,16 +24,23 @@ class CloudEvent : public Event { public: enum : int32_t { CLOUD_RDB_FEATURE_INIT = EVT_CLOUD, + CLOUD_RDB_OPEN_STORE, CLOUD_BUTT }; - CloudEvent(int32_t evtId, int32_t user); + CloudEvent(int32_t evtId, uint32_t tokenId, std::string storeName, std::string bundleName); ~CloudEvent() = default; - int32_t GetUser() const; +// int32_t GetUser() const; + std::string GetBundleName() const; + uint32_t GetTokenId() const; bool Equals(const DistributedData::Event &event) const override; private: - int32_t user_; +// int32_t user_; + std::string bundleName_; + uint32_t tokenId_; + std::string storeName_ + }; } // namespace OHOS::DistributedData #endif // OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_CLOUD_CLOUD_EVENT_H diff --git a/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_info.h b/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_info.h index baddad95..f87c1d03 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_info.h +++ b/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_info.h @@ -37,6 +37,7 @@ public: std::string GetKey() const; std::map GetSchemaKey() const; + std::string GetSchemaKey(std::string bundleName) const; bool IsValid() const; bool IsExist(const std::string &bundleName) const; void DelApp(const std::string &bundleName); diff --git a/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.cpp b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.cpp index 8de4f2cf..82a266a4 100644 --- a/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.cpp +++ b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.cpp @@ -19,20 +19,21 @@ #include "account/account_delegate.h" #include "checker/checker_manager.h" -#include "cloud_syncer.h" #include "cloud/cloud_event.h" #include "cloud/cloud_server.h" +#include "cloud_syncer.h" #include "eventcenter/event_center.h" #include "feature/feature_system.h" #include "ipc_skeleton.h" -#include "utils/anonymous.h" #include "log_print.h" #include "metadata/meta_data_manager.h" +#include "utils/anonymous.h" namespace OHOS::CloudData { using namespace DistributedData; __attribute__((used)) CloudServiceImpl::Factory CloudServiceImpl::factory_; -CloudServiceImpl::Factory::Factory() { +CloudServiceImpl::Factory::Factory() +{ FeatureSystem::GetInstance().RegisterCreator(CloudServiceImpl::SERVICE_NAME, [this]() { if (product_ == nullptr) { product_ = std::make_shared(); @@ -48,14 +49,42 @@ CloudServiceImpl::CloudServiceImpl() EventCenter::GetInstance().Subscribe(CloudEvent::CLOUD_RDB_FEATURE_INIT, [this](const Event &event) { auto &rdbEvent = static_cast(event); CloudInfo cloudInfo; - cloudInfo.user = rdbEvent.GetUser(); + cloudInfo.user = DistributedKv::AccountDelegate::GetInstance()->GetUserByToken(rdbEvent.GetTokenId()); if (GetServerInfo(cloudInfo) != SUCCESS) { - ZLOGE("failed, user:%{public}d", rdbEvent.GetUser()); + ZLOGE("failed, user:%{public}d", cloudInfo.user); return; } UpdateCloudInfo(cloudInfo); AddSchema(cloudInfo); }); + + EventCenter::GetInstance().Subscribe(CloudEvent::CLOUD_RDB_OPEN_STORE, [this](const Event &event) { + auto &rdbEvent = static_cast(event); + CloudInfo cloudInfo; + cloudInfo.user = DistributedKv::AccountDelegate::GetInstance()->GetUserByToken(rdbEvent.GetTokenId()); + if (GetServerInfo(cloudInfo) != SUCCESS) { + ZLOGE("failed, user:%{public}d", cloudInfo.user); + return; + } + auto instance = CloudServer::GetInstance(); + if (instance == nullptr) { + return; + } + SchemaMeta schemaMeta; + if (!MetaDataManager::GetInstance().LoadMeta(cloudInfo.GetSchemaKey(rdbEvent.GetBundleName()), schemaMeta, + true)) { + schemaMeta = instance->GetAppSchema(cloudInfo.user, rdbEvent.GetBundleName()); + MetaDataManager::GetInstance().SaveMeta(cloudInfo.GetSchemaKey(rdbEvent.GetBundleName()), schemaMeta, true); + } + + for (auto &database : schemaMeta.databases) { + if (false) { //TODO:不需要同步 + continue; + } + auto cloudDB = instance->ConnectCloudDB(rdbEvent.GetTokenId(), database); + //TODO:同步 + } + }); } int32_t CloudServiceImpl::EnableCloud(const std::string &id, const std::map &switches) @@ -146,7 +175,7 @@ int32_t CloudServiceImpl::Config(const std::string &id, const StoreInfo &storeIn auto tokenId = IPCSkeleton::GetCallingTokenID(); CloudInfo cloudInfo; cloudInfo.id = id; - cloudInfo.user = DistributedKv::AccountDelegate::GetInstance()->GetUserByToken(tokenId);; + cloudInfo.user = DistributedKv::AccountDelegate::GetInstance()->GetUserByToken(tokenId); if (ConfigCloudInfo(storeInfo, cloudInfo) != SUCCESS) { return ERROR; } @@ -173,8 +202,7 @@ int32_t CloudServiceImpl::ConfigCloudInfo(const StoreInfo &storeInfo, CloudInfo return SUCCESS; } -int32_t CloudServiceImpl::GetStoreSchema( - const CloudInfo &cloudInfo, const StoreInfo &storeInfo, std::string &schema) +int32_t CloudServiceImpl::GetStoreSchema(const CloudInfo &cloudInfo, const StoreInfo &storeInfo, std::string &schema) { if (!cloudInfo.IsExist(storeInfo.bundleName)) { ZLOGE("no exist bundleName:%{public}s", storeInfo.bundleName.c_str()); @@ -221,8 +249,8 @@ int32_t CloudServiceImpl::GetCloudInfo(CloudInfo &cloudInfo) auto tokenId = IPCSkeleton::GetCallingTokenID(); cloudInfo.user = DistributedKv::AccountDelegate::GetInstance()->GetUserByToken(tokenId); if (!MetaDataManager::GetInstance().LoadMeta(cloudInfo.GetKey(), cloudInfo, true)) { - ZLOGE("invalid argument id:%{public}s, user:%{public}d", - Anonymous::Change(cloudInfo.id).c_str(), cloudInfo.user); + ZLOGE("invalid argument id:%{public}s, user:%{public}d", Anonymous::Change(cloudInfo.id).c_str(), + cloudInfo.user); return ERROR; } return SUCCESS; @@ -287,8 +315,7 @@ void CloudServiceImpl::AddSchema(CloudInfo &cloudInfo) } } -int32_t CloudServiceImpl::GetAppSchema( - int32_t user, const std::string &bundleName, SchemaMeta &schemaMeta) +int32_t CloudServiceImpl::GetAppSchema(int32_t user, const std::string &bundleName, SchemaMeta &schemaMeta) { auto instance = CloudServer::GetInstance(); if (instance == nullptr) { @@ -300,11 +327,14 @@ int32_t CloudServiceImpl::GetAppSchema( void CloudServiceImpl::UpdateSchema(CloudInfo &cloudInfo, const StoreInfo &storeInfo, int32_t version) { - auto keys = cloudInfo.GetSchemaKey(); SchemaMeta schemaMeta; - if (!MetaDataManager::GetInstance().LoadMeta(keys[storeInfo.bundleName], schemaMeta, true)) { - AddSchema(cloudInfo); - return; + auto key = cloudInfo.GetSchemaKey(storeInfo.bundleName); + if (!MetaDataManager::GetInstance().LoadMeta(key, schemaMeta, true)) { + if (GetAppSchema(cloudInfo.user, storeInfo.bundleName, schemaMeta) != SUCCESS) { + ZLOGI("get schema meta fail"); + return; + } + MetaDataManager::GetInstance().SaveMeta(key, schemaMeta, true); } if (version <= schemaMeta.version) { ZLOGI("input ver:%{public}d, meta ver:%{public}d", version, schemaMeta.version); @@ -319,6 +349,6 @@ void CloudServiceImpl::UpdateSchema(CloudInfo &cloudInfo, const StoreInfo &store ZLOGI("input ver:%{public}d, server ver:%{public}d", version, serverMeta.version); return; } - MetaDataManager::GetInstance().SaveMeta(keys[storeInfo.bundleName], serverMeta, true); + MetaDataManager::GetInstance().SaveMeta(key, serverMeta, true); } -} // OHOS::CloudData \ No newline at end of file +} // namespace OHOS::CloudData \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.h b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.h index afb98b0c..0df774ea 100644 --- a/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.h +++ b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.h @@ -58,6 +58,7 @@ private: std::string GetAppId(const std::string &bundleName); bool CheckAccess(const std::string &bundleName); std::mutex mutex_; + ConcurrentMap clousInfos_; }; } // namespace OHOS::DistributedData diff --git a/datamgr_service/services/distributeddataservice/service/data_share/data_share_service_stub.cpp b/datamgr_service/services/distributeddataservice/service/data_share/data_share_service_stub.cpp index ba7fe7c7..f5c2fbac 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/data_share_service_stub.cpp +++ b/datamgr_service/services/distributeddataservice/service/data_share/data_share_service_stub.cpp @@ -21,6 +21,7 @@ #include "ishared_result_set.h" #include "itypes_util.h" #include "log_print.h" +#include "utils/anonymous.h" namespace OHOS { namespace DataShare { @@ -40,13 +41,14 @@ int32_t DataShareServiceStub::OnRemoteInsert(MessageParcel &data, MessageParcel std::string uri; DataShareValuesBucket bucket; if (!ITypesUtil::Unmarshal(data, uri, bucket.valuesMap)) { - ZLOGW("read device list failed."); - return -1; + ZLOGE("Unmarshal uri:%{public}s bucket size:%{public}zu", DistributedData::Anonymous::Change(uri).c_str(), + bucket.valuesMap.size()); + return IPC_STUB_INVALID_DATA_ERR; } int32_t status = Insert(uri, bucket); - if (!reply.WriteInt32(static_cast(status))) { - ZLOGE("OnRemoteInsert fail %{public}d", static_cast(status)); - return -1; + if (!ITypesUtil::Marshal(reply, status)) { + ZLOGE("Marshal status:0x%{public}x", status); + return IPC_STUB_WRITE_PARCEL_ERR; } return 0; } @@ -57,13 +59,14 @@ int32_t DataShareServiceStub::OnRemoteUpdate(MessageParcel &data, MessageParcel DataSharePredicates predicate; DataShareValuesBucket bucket; if (!ITypesUtil::Unmarshal(data, uri, predicate, bucket.valuesMap)) { - ZLOGW("read device list failed."); - return -1; + ZLOGE("Unmarshal uri:%{public}s bucket size:%{public}zu", DistributedData::Anonymous::Change(uri).c_str(), + bucket.valuesMap.size()); + return IPC_STUB_INVALID_DATA_ERR; } int32_t status = Update(uri, predicate, bucket); - if (!reply.WriteInt32(static_cast(status))) { - ZLOGE("OnRemoteUpdate fail %d", static_cast(status)); - return -1; + if (!ITypesUtil::Marshal(reply, status)) { + ZLOGE("Marshal status:0x%{public}x", status); + return IPC_STUB_WRITE_PARCEL_ERR; } return 0; } @@ -73,13 +76,13 @@ int32_t DataShareServiceStub::OnRemoteDelete(MessageParcel &data, MessageParcel std::string uri; DataSharePredicates predicate; if (!ITypesUtil::Unmarshal(data, uri, predicate)) { - ZLOGW("read device list failed."); - return -1; + ZLOGE("Unmarshal uri:%{public}s", DistributedData::Anonymous::Change(uri).c_str()); + return IPC_STUB_INVALID_DATA_ERR; } int32_t status = Delete(uri, predicate); - if (!reply.WriteInt32(static_cast(status))) { - ZLOGE("OnRemoteDelete fail %d", static_cast(status)); - return -1; + if (!ITypesUtil::Marshal(reply, status)) { + ZLOGE("Marshal status:0x%{public}x", status); + return IPC_STUB_WRITE_PARCEL_ERR; } return 0; } @@ -90,15 +93,16 @@ int32_t DataShareServiceStub::OnRemoteQuery(MessageParcel &data, MessageParcel & DataSharePredicates predicate; std::vector columns; if (!ITypesUtil::Unmarshal(data, uri, predicate, columns)) { - ZLOGW("read device list failed."); - return -1; + ZLOGE("Unmarshal uri:%{public}s columns size:%{public}zu", DistributedData::Anonymous::Change(uri).c_str(), + columns.size()); + return IPC_STUB_INVALID_DATA_ERR; } - int errCode = 0; - auto result = ISharedResultSet::WriteToParcel(Query(uri, predicate, columns, errCode), reply); - reply.WriteInt32(errCode); - if (result == nullptr) { - ZLOGW("!resultSet->Marshalling(reply)"); - return -1; + int status = 0; + auto result = ISharedResultSet::WriteToParcel(Query(uri, predicate, columns, status), reply); + reply.WriteInt32(status); + if (!ITypesUtil::Marshal(reply, status)) { + ZLOGE("Marshal status:0x%{public}x", status); + return IPC_STUB_WRITE_PARCEL_ERR; } return 0; } diff --git a/datamgr_service/services/distributeddataservice/service/object/object_service_stub.cpp b/datamgr_service/services/distributeddataservice/service/object/object_service_stub.cpp index cf142a29..a7118b31 100644 --- a/datamgr_service/services/distributeddataservice/service/object/object_service_stub.cpp +++ b/datamgr_service/services/distributeddataservice/service/object/object_service_stub.cpp @@ -21,6 +21,7 @@ #include "itypes_util.h" #include "log_print.h" +#include "utils/anonymous.h" namespace OHOS::DistributedObject { using namespace DistributedKv; @@ -32,17 +33,19 @@ int32_t ObjectServiceStub::ObjectStoreSaveOnRemote(MessageParcel &data, MessageP std::map> objectData; sptr obj; if (!ITypesUtil::Unmarshal(data, bundleName, sessionId, deviceId, objectData, obj)) { - ZLOGW("read device list failed."); - return -1; + ZLOGE("Unmarshal sessionId:%{public}s bundleName:%{public}s deviceId:%{public}s objectData size:%{public}zu", + sessionId.c_str(), bundleName.c_str(), DistributedData::Anonymous::Change(deviceId).c_str(), + objectData.size()); + return IPC_STUB_INVALID_DATA_ERR; } if (obj == nullptr) { ZLOGW("callback null"); return -1; } int32_t status = ObjectStoreSave(bundleName, sessionId, deviceId, objectData, obj); - if (!reply.WriteInt32(static_cast(status))) { - ZLOGE("ObjectStoreSaveOnRemote fail %{public}d", static_cast(status)); - return -1; + if (!ITypesUtil::Marshal(reply, status)) { + ZLOGE("Marshal status:0x%{public}x", status); + return IPC_STUB_WRITE_PARCEL_ERR; } return 0; } @@ -53,17 +56,17 @@ int32_t ObjectServiceStub::ObjectStoreRevokeSaveOnRemote(MessageParcel &data, Me std::string bundleName; sptr obj; if (!ITypesUtil::Unmarshal(data, bundleName, sessionId, obj)) { - ZLOGW("read device list failed."); - return -1; + ZLOGE("Unmarshal sessionId:%{public}s bundleName:%{public}s", sessionId.c_str(), bundleName.c_str()); + return IPC_STUB_INVALID_DATA_ERR; } if (obj == nullptr) { ZLOGW("callback null"); return -1; } int32_t status = ObjectStoreRevokeSave(bundleName, sessionId, obj); - if (!reply.WriteInt32(static_cast(status))) { - ZLOGE("ObjectStoreRevokeSaveOnRemote fail %{public}d", static_cast(status)); - return -1; + if (!ITypesUtil::Marshal(reply, status)) { + ZLOGE("Marshal status:0x%{public}x", status); + return IPC_STUB_WRITE_PARCEL_ERR; } return 0; } @@ -74,17 +77,17 @@ int32_t ObjectServiceStub::ObjectStoreRetrieveOnRemote(MessageParcel &data, Mess std::string bundleName; sptr obj; if (!ITypesUtil::Unmarshal(data, bundleName, sessionId, obj)) { - ZLOGW("read device list failed."); - return -1; + ZLOGE("Unmarshal sessionId:%{public}s bundleName:%{public}s", sessionId.c_str(), bundleName.c_str()); + return IPC_STUB_INVALID_DATA_ERR; } if (obj == nullptr) { ZLOGW("callback null"); return -1; } int32_t status = ObjectStoreRetrieve(bundleName, sessionId, obj); - if (!reply.WriteInt32(static_cast(status))) { - ZLOGE("ObjectStoreRetrieveOnRemote fail %{public}d", static_cast(status)); - return -1; + if (!ITypesUtil::Marshal(reply, status)) { + ZLOGE("Marshal status:0x%{public}x", status); + return IPC_STUB_WRITE_PARCEL_ERR; } return 0; } @@ -95,17 +98,17 @@ int32_t ObjectServiceStub::OnSubscribeRequest(MessageParcel &data, MessageParcel std::string bundleName; sptr obj; if (!ITypesUtil::Unmarshal(data, bundleName, sessionId, obj)) { - ZLOGW("read device list failed."); - return -1; + ZLOGE("Unmarshal sessionId:%{public}s bundleName:%{public}s", sessionId.c_str(), bundleName.c_str()); + return IPC_STUB_INVALID_DATA_ERR; } if (obj == nullptr) { ZLOGW("callback null"); return -1; } int32_t status = RegisterDataObserver(bundleName, sessionId, obj); - if (!reply.WriteInt32(static_cast(status))) { - ZLOGE("OnSubscribeRequest fail %{public}d", static_cast(status)); - return -1; + if (!ITypesUtil::Marshal(reply, status)) { + ZLOGE("Marshal status:0x%{public}x", status); + return IPC_STUB_WRITE_PARCEL_ERR; } return 0; } @@ -115,13 +118,13 @@ int32_t ObjectServiceStub::OnUnsubscribeRequest(MessageParcel &data, MessageParc std::string sessionId; std::string bundleName; if (!ITypesUtil::Unmarshal(data, bundleName, sessionId)) { - ZLOGW("read device list failed."); - return -1; + ZLOGE("Unmarshal sessionId:%{public}s bundleName:%{public}s", sessionId.c_str(), bundleName.c_str()); + return IPC_STUB_INVALID_DATA_ERR; } int32_t status = UnregisterDataChangeObserver(bundleName, sessionId); - if (!reply.WriteInt32(static_cast(status))) { - ZLOGE("OnSubscribeRequest fail %{public}d", static_cast(status)); - return -1; + if (!ITypesUtil::Marshal(reply, status)) { + ZLOGE("Marshal status:0x%{public}x", status); + return IPC_STUB_WRITE_PARCEL_ERR; } return 0; } diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.cpp b/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.cpp index a0a29d01..29ecbddc 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.cpp +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.cpp @@ -159,6 +159,13 @@ std::string RdbServiceImpl::ObtainDistributedTableName(const std::string &device return DistributedDB::RelationalStoreManager::GetDistributedTableName(uuid, table); } +int32_t OpenStore(const CloudParam &cloudParam) +{ + auto event = + std::make_unique(CloudEvent::CLOUD_RDB_OPEN_STORE, IPCSkeleton::GetCallingTokenID(), cloudParam.storeName, cloudParam.bundleName); + EventCenter::GetInstance().PostEvent(move(event)); +} + int32_t RdbServiceImpl::InitNotifier(const RdbSyncerParam& param, const sptr notifier) { if (!CheckAccess(param)) { diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.h b/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.h index 0961337a..7203622e 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.h +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.h @@ -43,6 +43,8 @@ public: int32_t InitNotifier(const RdbSyncerParam& param, const sptr notifier) override; + int32_t OpenStore(const CloudParam &cloudParam) override; + int32_t SetDistributedTables(const RdbSyncerParam& param, const std::vector& tables) override; int32_t RemoteQuery(const RdbSyncerParam& param, const std::string& device, const std::string& sql, diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_stub.cpp b/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_stub.cpp index 137a0598..67885150 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_stub.cpp +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_stub.cpp @@ -19,6 +19,7 @@ #include #include "log_print.h" #include "itypes_util.h" +#include "utils/anonymous.h" namespace OHOS::DistributedRdb { int32_t RdbServiceStub::OnRemoteObtainDistributedTableName(MessageParcel &data, MessageParcel &reply) @@ -26,12 +27,30 @@ int32_t RdbServiceStub::OnRemoteObtainDistributedTableName(MessageParcel &data, std::string device; std::string table; if (!ITypesUtil::Unmarshal(data, device, table)) { - ZLOGE("read from message parcel failed"); - reply.WriteString(""); - return RDB_OK; + ZLOGE("Unmarshal device:%{public}s table:%{public}s", device.c_str(), table.c_str()); + return IPC_STUB_INVALID_DATA_ERR; } - reply.WriteString(ObtainDistributedTableName(device, table)); + std::string distributedTableName = ObtainDistributedTableName(device, table); + if (!ITypesUtil::Marshal(reply, distributedTableName)) { + ZLOGE("Marshal distributedTableName:%{public}s", distributedTableName.c_str()); + return IPC_STUB_WRITE_PARCEL_ERR; + } + return RDB_OK; +} + +int32_t RdbServiceStub::OnOpenStore(MessageParcel &data, MessageParcel &reply) { + CloudParam cloudParam; + if (!ITypesUtil::Unmarshal(data, cloudParam)) { + ZLOGE("Unmarshal bundleName_:%{public}s storeName_:%{public}s", cloudParam.bundleName.c_str(), + cloudParam.storeName.c_str()); + return IPC_STUB_INVALID_DATA_ERR; + } + auto status = OpenStore(cloudParam); + if (!ITypesUtil::Marshal(reply, status)) { + ZLOGE("Marshal status:0x%{public}x", status); + return IPC_STUB_WRITE_PARCEL_ERR; + } return RDB_OK; } @@ -39,14 +58,17 @@ int32_t RdbServiceStub::OnRemoteInitNotifier(MessageParcel &data, MessageParcel { RdbSyncerParam param; sptr notifier; - if (!ITypesUtil::Unmarshal(data, param, notifier)) { - ZLOGE("read from message parcel failed"); - reply.WriteInt32(RDB_ERROR); - return RDB_OK; + if (!ITypesUtil::Unmarshal(data, param, notifier) || notifier == nullptr) { + ZLOGE("Unmarshal bundleName_:%{public}s storeName_:%{public}s", param.bundleName_.c_str(), + param.storeName_.c_str()); + return IPC_STUB_INVALID_DATA_ERR; } - auto status = InitNotifier(param, notifier); - return ITypesUtil::Marshal(reply, status) ? RDB_OK : RDB_ERROR; + if (!ITypesUtil::Marshal(reply, status)) { + ZLOGE("Marshal status:0x%{public}x", status); + return IPC_STUB_WRITE_PARCEL_ERR; + } + return RDB_OK; } int32_t RdbServiceStub::OnRemoteSetDistributedTables(MessageParcel &data, MessageParcel &reply) @@ -54,13 +76,17 @@ int32_t RdbServiceStub::OnRemoteSetDistributedTables(MessageParcel &data, Messag RdbSyncerParam param; std::vector tables; if (!ITypesUtil::Unmarshal(data, param, tables)) { - ZLOGE("read from message parcel failed"); - reply.WriteInt32(RDB_ERROR); - return RDB_OK; + ZLOGE("Unmarshal bundleName_:%{public}s storeName_:%{public}s tables size:%{public}zu", + param.bundleName_.c_str(), param.storeName_.c_str(), tables.size()); + return IPC_STUB_INVALID_DATA_ERR; } auto status = SetDistributedTables(param, tables); - return ITypesUtil::Marshal(reply, status) ? RDB_OK : RDB_ERROR; + if (!ITypesUtil::Marshal(reply, status)) { + ZLOGE("Marshal status:0x%{public}x", status); + return IPC_STUB_WRITE_PARCEL_ERR; + } + return RDB_OK; } int32_t RdbServiceStub::OnRemoteDoSync(MessageParcel &data, MessageParcel &reply) @@ -69,14 +95,18 @@ int32_t RdbServiceStub::OnRemoteDoSync(MessageParcel &data, MessageParcel &reply SyncOption option {}; RdbPredicates predicates; if (!ITypesUtil::Unmarshal(data, param, option, predicates)) { - ZLOGE("read from message parcel failed"); - reply.WriteInt32(RDB_ERROR); - return RDB_OK; + ZLOGE("Unmarshal bundleName_:%{public}s storeName_:%{public}s tables:%{public}s", param.bundleName_.c_str(), + param.storeName_.c_str(), predicates.table_.c_str()); + return IPC_STUB_INVALID_DATA_ERR; } SyncResult result; auto status = DoSync(param, option, predicates, result); - return ITypesUtil::Marshal(reply, status, result) ? RDB_OK : RDB_ERROR; + if (!ITypesUtil::Marshal(reply, status, result)) { + ZLOGE("Marshal status:0x%{public}x result size:%{public}zu", status, result.size()); + return IPC_STUB_WRITE_PARCEL_ERR; + } + return RDB_OK; } int32_t RdbServiceStub::OnRemoteDoAsync(MessageParcel &data, MessageParcel &reply) @@ -86,24 +116,33 @@ int32_t RdbServiceStub::OnRemoteDoAsync(MessageParcel &data, MessageParcel &repl SyncOption option {}; RdbPredicates predicates; if (!ITypesUtil::Unmarshal(data, param, seqNum, option, predicates)) { - ZLOGE("read from message parcel failed"); - reply.WriteInt32(RDB_ERROR); - return RDB_OK; + ZLOGE("Unmarshal bundleName_:%{public}s storeName_:%{public}s seqNum:%{public}u tables:%{public}s", + param.bundleName_.c_str(), param.storeName_.c_str(), seqNum, predicates.table_.c_str()); + return IPC_STUB_INVALID_DATA_ERR; } auto status = DoAsync(param, seqNum, option, predicates); - return ITypesUtil::Marshal(reply, status) ? RDB_OK : RDB_ERROR; + if (!ITypesUtil::Marshal(reply, status)) { + ZLOGE("Marshal status:0x%{public}x", status); + return IPC_STUB_WRITE_PARCEL_ERR; + } + return RDB_OK; } int32_t RdbServiceStub::OnRemoteDoSubscribe(MessageParcel &data, MessageParcel &reply) { RdbSyncerParam param; if (!ITypesUtil::Unmarshal(data, param)) { - ZLOGE("read from message parcel failed"); - reply.WriteInt32(RDB_ERROR); - return RDB_OK; + ZLOGE("Unmarshal bundleName_:%{public}s storeName_:%{public}s", param.bundleName_.c_str(), + param.storeName_.c_str()); + return IPC_STUB_INVALID_DATA_ERR; + } + + auto status = DoSubscribe(param); + if (!ITypesUtil::Marshal(reply, status)) { + ZLOGE("Marshal status:0x%{public}x", status); + return IPC_STUB_WRITE_PARCEL_ERR; } - reply.WriteInt32(DoSubscribe(param)); return RDB_OK; } @@ -111,11 +150,16 @@ int32_t RdbServiceStub::OnRemoteDoUnSubscribe(MessageParcel &data, MessageParcel { RdbSyncerParam param; if (!ITypesUtil::Unmarshal(data, param)) { - ZLOGE("read from message parcel failed"); - reply.WriteInt32(RDB_ERROR); - return RDB_OK; + ZLOGE("Unmarshal bundleName_:%{public}s storeName_:%{public}s", param.bundleName_.c_str(), + param.storeName_.c_str()); + return IPC_STUB_INVALID_DATA_ERR; + } + + auto status = DoUnSubscribe(param); + if (!ITypesUtil::Marshal(reply, status)) { + ZLOGE("Marshal status:0x%{public}x", status); + return IPC_STUB_WRITE_PARCEL_ERR; } - reply.WriteInt32(DoUnSubscribe(param)); return RDB_OK; } @@ -126,14 +170,20 @@ int32_t RdbServiceStub::OnRemoteDoRemoteQuery(MessageParcel& data, MessageParcel std::string sql; std::vector selectionArgs; if (!ITypesUtil::Unmarshal(data, param, device, sql, selectionArgs)) { - ZLOGE("read from message parcel failed"); - reply.WriteInt32(RDB_ERROR); - return RDB_OK; + ZLOGE("Unmarshal bundleName_:%{public}s storeName_:%{public}s device:%{public}s sql:%{public}s " + "selectionArgs size:%{public}zu", param.bundleName_.c_str(), param.storeName_.c_str(), + DistributedData::Anonymous::Change(device).c_str(), + DistributedData::Anonymous::Change(sql).c_str(), selectionArgs.size()); + return IPC_STUB_INVALID_DATA_ERR; } sptr resultSet; - int32_t status = RemoteQuery(param, device, sql, selectionArgs, resultSet); - return ITypesUtil::Marshal(reply, status, resultSet) ? RDB_OK : RDB_ERROR; + auto status = RemoteQuery(param, device, sql, selectionArgs, resultSet); + if (!ITypesUtil::Marshal(reply, status, resultSet)) { + ZLOGE("Marshal status:0x%{public}x", status); + return IPC_STUB_WRITE_PARCEL_ERR; + } + return RDB_OK; } bool RdbServiceStub::CheckInterfaceToken(MessageParcel& data) @@ -165,25 +215,35 @@ int32_t RdbServiceStub::OnRemoteDoCreateTable(MessageParcel &data, MessageParcel std::string writePermission; std::string readPermission; if (!ITypesUtil::Unmarshal(data, param, writePermission, readPermission)) { - ZLOGE("read from message parcel failed"); - reply.WriteInt32(RDB_ERROR); - return RDB_OK; + ZLOGE("Unmarshal bundleName_:%{public}s storeName_:%{public}s writePermission:%{public}s " + "readPermission:%{public}s", param.bundleName_.c_str(), param.storeName_.c_str(), + DistributedData::Anonymous::Change(writePermission).c_str(), + DistributedData::Anonymous::Change(readPermission).c_str()); + return IPC_STUB_INVALID_DATA_ERR; } int32_t status = CreateRDBTable(param, writePermission, readPermission); - return ITypesUtil::Marshal(reply, status) ? RDB_OK : RDB_ERROR; + if (!ITypesUtil::Marshal(reply, status)) { + ZLOGE("Marshal status:0x%{public}x", status); + return IPC_STUB_WRITE_PARCEL_ERR; + } + return RDB_OK; } int32_t RdbServiceStub::OnRemoteDoDestroyTable(MessageParcel &data, MessageParcel &reply) { RdbSyncerParam param; if (!ITypesUtil::Unmarshal(data, param)) { - ZLOGE("read from message parcel failed"); - reply.WriteInt32(RDB_ERROR); - return RDB_OK; + ZLOGE("Unmarshal bundleName_:%{public}s storeName_:%{public}s", param.bundleName_.c_str(), + param.storeName_.c_str()); + return IPC_STUB_INVALID_DATA_ERR; } int32_t status = DestroyRDBTable(param); - return ITypesUtil::Marshal(reply, status) ? RDB_OK : RDB_ERROR; + if (!ITypesUtil::Marshal(reply, status)) { + ZLOGE("Marshal status:0x%{public}x", status); + return IPC_STUB_WRITE_PARCEL_ERR; + } + return RDB_OK; } } // namespace OHOS::DistributedRdb diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_stub.h b/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_stub.h index 901a7d6e..0758ad9c 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_stub.h +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_stub.h @@ -50,6 +50,8 @@ private: int32_t OnRemoteObtainDistributedTableName(MessageParcel& data, MessageParcel& reply); + int32_t OnOpenStore(MessageParcel&data, MessageParcel& reply); + int32_t OnRemoteInitNotifier(MessageParcel&data, MessageParcel& reply); int32_t OnRemoteSetDistributedTables(MessageParcel &data, MessageParcel &reply); @@ -79,7 +81,8 @@ private: [RDB_SERVICE_CMD_UNSUBSCRIBE] = &RdbServiceStub::OnRemoteDoUnSubscribe, [RDB_SERVICE_CMD_REMOTE_QUERY] = &RdbServiceStub::OnRemoteDoRemoteQuery, [RDB_SERVICE_CREATE_RDB_TABLE] = &RdbServiceStub::OnRemoteDoCreateTable, - [RDB_SERVICE_DESTROY_RDB_TABLE] = &RdbServiceStub::OnRemoteDoDestroyTable + [RDB_SERVICE_DESTROY_RDB_TABLE] = &RdbServiceStub::OnRemoteDoDestroyTable, + [RDB_SERVICE_CMD_OPEN_STORE] = &RdbServiceStub::OnOpenStore }; }; } // namespace OHOS::DistributedRdb diff --git a/relational_store/frameworks/js/napi/rdb/src/napi_rdb_store_helper.cpp b/relational_store/frameworks/js/napi/rdb/src/napi_rdb_store_helper.cpp index 7f1742ae..ed233346 100644 --- a/relational_store/frameworks/js/napi/rdb/src/napi_rdb_store_helper.cpp +++ b/relational_store/frameworks/js/napi/rdb/src/napi_rdb_store_helper.cpp @@ -451,6 +451,7 @@ napi_value InnerGetRdbStore(napi_env env, napi_callback_info info, std::shared_p int errCode = OK; DefaultOpenCallback callback; context->proxy = RdbHelper::GetRdbStore(context->config, context->version, callback, errCode); + std::shared_ptr dbInvalidError = std::make_shared(); RDB_CHECK_RETURN_CALL_RESULT(errCode == E_OK && context->proxy != nullptr, context->SetError(dbInvalidError)); return (errCode == E_OK) ? OK : ERR; diff --git a/relational_store/frameworks/native/rdb/include/rdb_service_proxy.h b/relational_store/frameworks/native/rdb/include/rdb_service_proxy.h index b7166e23..50a20253 100644 --- a/relational_store/frameworks/native/rdb/include/rdb_service_proxy.h +++ b/relational_store/frameworks/native/rdb/include/rdb_service_proxy.h @@ -33,6 +33,7 @@ public: std::string ObtainDistributedTableName(const std::string& device, const std::string& table) override; + int32_t OpenStore(const CloudParam &cloudParam) override; int32_t InitNotifier(const RdbSyncerParam& param); int32_t InitNotifier(const RdbSyncerParam& param, const sptr notifier) override; diff --git a/relational_store/frameworks/native/rdb/include/rdb_types_util.h b/relational_store/frameworks/native/rdb/include/rdb_types_util.h index 71dcf135..ca4465ae 100644 --- a/relational_store/frameworks/native/rdb/include/rdb_types_util.h +++ b/relational_store/frameworks/native/rdb/include/rdb_types_util.h @@ -22,6 +22,7 @@ #include "rdb_visibility.h" namespace OHOS::ITypesUtil { using SyncerParam = DistributedRdb::RdbSyncerParam; +using CloudParam = DistributedRdb::CloudParam; using SyncOption = DistributedRdb::SyncOption; using RdbPredicates = DistributedRdb::RdbPredicates; using RdbOperation = DistributedRdb::RdbPredicateOperation; @@ -33,6 +34,10 @@ RDB_API_EXPORT bool Marshalling(const SyncerParam &input, MessageParcel &data); template<> RDB_API_EXPORT bool Unmarshalling(SyncerParam &output, MessageParcel &data); template<> +RDB_API_EXPORT bool Marshalling(const CloudParam &input, MessageParcel &data); +template<> +RDB_API_EXPORT bool Unmarshalling(CloudParam &output, MessageParcel &data); +template<> RDB_API_EXPORT bool Marshalling(const SyncOption &input, MessageParcel &data); template<> RDB_API_EXPORT bool Unmarshalling(SyncOption &output, MessageParcel &data); diff --git a/relational_store/frameworks/native/rdb/src/rdb_service_proxy.cpp b/relational_store/frameworks/native/rdb/src/rdb_service_proxy.cpp index 760709ad..1b0cb411 100644 --- a/relational_store/frameworks/native/rdb/src/rdb_service_proxy.cpp +++ b/relational_store/frameworks/native/rdb/src/rdb_service_proxy.cpp @@ -342,4 +342,15 @@ int32_t RdbServiceProxy::DestroyRDBTable(const RdbSyncerParam ¶m) } return status; } + +int32_t RdbServiceProxy::OpenStore(const CloudParam &cloudParam) +{ + MessageParcel reply; + int32_t status = IPC_SEND(RDB_SERVICE_CMD_OPEN_STORE, reply, cloudParam); + if (status != RDB_OK) { + ZLOGE("status:%{public}d, bundleName:%{public}s, storeName:%{public}s", status, cloudParam.bundleName.c_str(), + cloudParam.storeName.c_str()); + } + return status; +} } // namespace OHOS::DistributedRdb diff --git a/relational_store/frameworks/native/rdb/src/rdb_store_manager.cpp b/relational_store/frameworks/native/rdb/src/rdb_store_manager.cpp index a5e8bb47..c8e2e8e5 100644 --- a/relational_store/frameworks/native/rdb/src/rdb_store_manager.cpp +++ b/relational_store/frameworks/native/rdb/src/rdb_store_manager.cpp @@ -24,6 +24,7 @@ #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) #include "rdb_security_manager.h" #include "security_policy.h" +#include #endif namespace OHOS { diff --git a/relational_store/frameworks/native/rdb/src/rdb_types_util.cpp b/relational_store/frameworks/native/rdb/src/rdb_types_util.cpp index a45c56c2..bc423e6f 100644 --- a/relational_store/frameworks/native/rdb/src/rdb_types_util.cpp +++ b/relational_store/frameworks/native/rdb/src/rdb_types_util.cpp @@ -28,6 +28,15 @@ bool Unmarshalling(SyncerParam &output, MessageParcel &data) output.level_, output.type_, output.isAutoSync_, output.isEncrypt_, output.password_); } +template<> bool Marshalling(const CloudParam &input, MessageParcel &data) +{ + return ITypesUtil::Marshal(data, input.bundleName, input.storeName); +} +template<> bool Unmarshalling(CloudParam &output, MessageParcel &data) +{ + return ITypesUtil::Unmarshal(data, output.bundleName, output.storeName); +} + template<> bool Marshalling(const SyncOption &input, MessageParcel &data) { diff --git a/relational_store/interfaces/inner_api/rdb/include/rdb_service.h b/relational_store/interfaces/inner_api/rdb/include/rdb_service.h index a72ebf72..fe89a896 100644 --- a/relational_store/interfaces/inner_api/rdb/include/rdb_service.h +++ b/relational_store/interfaces/inner_api/rdb/include/rdb_service.h @@ -37,10 +37,13 @@ public: RDB_SERVICE_CMD_REMOTE_QUERY, RDB_SERVICE_CREATE_RDB_TABLE, RDB_SERVICE_DESTROY_RDB_TABLE, + RDB_SERVICE_CMD_OPEN_STORE, RDB_SERVICE_CMD_MAX }; virtual std::string ObtainDistributedTableName(const std::string &device, const std::string &table) = 0; + virtual int32_t OpenStore(const CloudParam &cloudParam) = 0; + virtual int32_t SetDistributedTables(const RdbSyncerParam ¶m, const std::vector &tables) = 0; virtual int32_t Sync(const RdbSyncerParam ¶m, const SyncOption &option, const RdbPredicates &predicates, -- Gitee From 8106315e4043431189a134f0ed71e07245c38973 Mon Sep 17 00:00:00 2001 From: htt1997 Date: Fri, 21 Apr 2023 10:01:30 +0800 Subject: [PATCH 20/44] update Signed-off-by: htt1997 --- .../native/consumer/src/datashare_helper.cpp | 29 +++++++++-- .../src/mediadatashare_unit_test.cpp | 42 ++++++++++++++-- .../framework/cloud/cloud_event.cpp | 25 +++++++++- .../framework/include/cloud/cloud_event.h | 10 +++- .../service/cloud/cloud_service_impl.cpp | 12 +++-- .../service/rdb/rdb_service_impl.cpp | 48 ++++++++++++------- .../service/rdb/rdb_service_impl.h | 4 +- .../innerkitsimpl/kvdb/src/dev_manager.cpp | 6 +-- .../distributedkvstore/src/js_util.cpp | 2 +- .../native/rdb/include/rdb_manager_impl.h | 2 +- .../native/rdb/include/rdb_service_proxy.h | 4 +- .../frameworks/native/rdb/src/rdb_manager.cpp | 2 +- .../native/rdb/src/rdb_manager_impl.cpp | 8 ++-- .../native/rdb/src/rdb_service_proxy.cpp | 11 ++--- .../native/rdb/src/rdb_store_config.cpp | 21 ++++++++ .../native/rdb/src/rdb_store_impl.cpp | 17 +++++++ .../native/rdb/src/rdb_store_manager.cpp | 2 +- .../inner_api/rdb/include/rdb_service.h | 8 ++-- .../inner_api/rdb/include/rdb_store_config.h | 26 ++++++++++ 19 files changed, 222 insertions(+), 57 deletions(-) diff --git a/data_share/frameworks/native/consumer/src/datashare_helper.cpp b/data_share/frameworks/native/consumer/src/datashare_helper.cpp index 312e4e9e..d606dfeb 100644 --- a/data_share/frameworks/native/consumer/src/datashare_helper.cpp +++ b/data_share/frameworks/native/consumer/src/datashare_helper.cpp @@ -21,6 +21,7 @@ #include "dataobs_mgr_client.h" #include "datashare_log.h" #include "datashare_result_set.h" +#include "concurrent_map.h" namespace OHOS { namespace DataShare { @@ -31,16 +32,20 @@ constexpr int INVALID_VALUE = -1; } // namespace class ObserverImpl : public AAFwk::DataAbilityObserverStub { public: + ObserverImpl() : dataShareObserver_(nullptr){}; explicit ObserverImpl(const std::shared_ptr dataShareObserver) : dataShareObserver_(dataShareObserver){}; void OnChange(); void OnChangeExt(const ChangeInfo &info); static DataShareObserver::ChangeInfo ConvertInfo(const AAFwk::ChangeInfo &info); static AAFwk::ChangeInfo ConvertInfo(const DataShareObserver::ChangeInfo &info); + static sptr GetInstance(const std::shared_ptr dataShareObserver, bool remove = false); private: std::shared_ptr dataShareObserver_; + static ConcurrentMap> obs_; }; +ConcurrentMap> ObserverImpl::obs_; DataShareHelper::DataShareHelper(const sptr &token, const Uri &uri, std::shared_ptr dataShareConnection) @@ -536,9 +541,10 @@ void DataShareHelper::RegisterObserverExt(const Uri &uri, std::shared_ptr obs(new (std::nothrow) ObserverImpl(dataObserver)); + auto obs = ObserverImpl::GetInstance(dataObserver); +// sptr obs(new (std::nothrow) ObserverImpl(dataObserver)); if (obs == nullptr) { - LOG_ERROR("new ObserverImpl failed"); + LOG_ERROR("get ObserverImpl failed"); return; } ErrCode ret = obsMgrClient->RegisterObserverExt(uri, obs, isDescendants); @@ -566,9 +572,9 @@ void DataShareHelper::UnregisterObserverExt(const Uri &uri, std::shared_ptr obs(new (std::nothrow) ObserverImpl(dataObserver)); + auto obs = ObserverImpl::GetInstance(dataObserver, true); if (obs == nullptr) { - LOG_ERROR("new ObserverImpl failed"); + LOG_ERROR("get ObserverImpl failed"); return; } ErrCode ret = obsMgrClient->UnregisterObserverExt(uri, obs); @@ -752,5 +758,20 @@ AAFwk::ChangeInfo ObserverImpl::ConvertInfo(const DataShareObserver::ChangeInfo changeInfo.size_ = info.size_; return changeInfo; } +sptr ObserverImpl::GetInstance(const std::shared_ptr dataShareObserver, bool remove) +{ + sptr result = nullptr; + obs_.Compute(dataShareObserver.get(), [&result, remove, dataShareObserver](const auto &key, auto &value) { + if (value == nullptr) { + sptr obs(new (std::nothrow) ObserverImpl(dataShareObserver)); + value = obs; + } + result = value; + return !remove && result != nullptr; + }); + + return result; +} + } // namespace DataShare } // namespace OHOS \ No newline at end of file diff --git a/data_share/test/native/unittest/mediadatashare_test/src/mediadatashare_unit_test.cpp b/data_share/test/native/unittest/mediadatashare_test/src/mediadatashare_unit_test.cpp index ad447fde..fe4c5966 100644 --- a/data_share/test/native/unittest/mediadatashare_test/src/mediadatashare_unit_test.cpp +++ b/data_share/test/native/unittest/mediadatashare_test/src/mediadatashare_unit_test.cpp @@ -1170,9 +1170,9 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_Observer_001, TestSize.Level0) LOG_INFO("MediaDataShare_Observer_001 end"); } -HWTEST_F(MediaDataShareUnitTest, MediaDataShare_ObserverExt_001, TestSize.Level0) +HWTEST_F(MediaDataShareUnitTest, MediaDataShare_RegisterObserverExt_001, TestSize.Level0) { - LOG_INFO("MediaDataShare_ObserverExt_001 start"); + LOG_INFO("MediaDataShare_RegisterObserverExt_001 start"); std::shared_ptr helper = g_mediaDataShareHelper; ASSERT_TRUE(helper != nullptr); Uri uri(MEDIALIBRARY_DATA_URI); @@ -1230,7 +1230,43 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_ObserverExt_001, TestSize.Level0 } helper->UnregisterObserverExt(uri, dataObserver); - LOG_INFO("MediaDataShare_ObserverExt_001 end"); + LOG_INFO("MediaDataShare_RegisterObserverExt_001 end"); +} + +HWTEST_F(MediaDataShareUnitTest, MediaDataShare_UnregisterObserverExt_001, TestSize.Level0) +{ + LOG_INFO("MediaDataShare_UnregisterObserverExt_001 start"); + std::shared_ptr helper = g_mediaDataShareHelper; + ASSERT_TRUE(helper != nullptr); + Uri uri(MEDIALIBRARY_DATA_URI); + std::shared_ptr dataObserver = std::make_shared(); + helper->RegisterObserverExt(uri, dataObserver, true); + + DataShare::DataShareValuesBucket valuesBucket; + valuesBucket.Put(MEDIA_DATA_DB_TITLE, "Datashare_Observer_Test001"); + int retVal = helper->Insert(uri, valuesBucket); + EXPECT_EQ((retVal > 0), true); + helper->NotifyChangeExt({ DataShareObserver::ChangeType::INSERT, { uri } }); + + { + unique_lock lock(dataObserver->mutex_); + if (dataObserver->condition_.wait_for(lock, 2s) == std::cv_status::no_timeout) { + EXPECT_TRUE(true); + } else { + EXPECT_TRUE(false); + } + } + helper->UnregisterObserverExt(uri, dataObserver); + helper->NotifyChangeExt({ DataShareObserver::ChangeType::DELETE, { uri } }); + { + unique_lock lock(dataObserver->mutex_); + if (dataObserver->condition_.wait_for(lock, 2s) == std::cv_status::no_timeout) { + EXPECT_TRUE(false); + } else { + EXPECT_TRUE(true); + } + } + LOG_INFO("MediaDataShare_UnregisterObserverExt_001 end"); } } // namespace Media } // namespace OHOS \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/framework/cloud/cloud_event.cpp b/datamgr_service/services/distributeddataservice/framework/cloud/cloud_event.cpp index 7ab8cbe7..5dd21727 100644 --- a/datamgr_service/services/distributeddataservice/framework/cloud/cloud_event.cpp +++ b/datamgr_service/services/distributeddataservice/framework/cloud/cloud_event.cpp @@ -16,8 +16,14 @@ #include "cloud/cloud_event.h" namespace OHOS::DistributedData { -CloudEvent::CloudEvent(int32_t evtId, uint32_t tokenId, std::string storeName, std::string bundleName) - : Event(evtId), tokenId_(tokenId), storeName_(storeName), bundleName_(bundleName) +CloudEvent::CloudEvent(int32_t evtId, uint32_t tokenId, std::string storeName, std::string bundleName, + std::string schemaKey) + : Event(evtId), tokenId_(tokenId), storeName_(storeName), bundleName_(bundleName), schemaKey_(schemaKey) +{ +} +CloudEvent::CloudEvent(int32_t evtId, const CloudEvent &cloudEvent) + : Event(evtId), tokenId_(cloudEvent.GetTokenId()), storeName_(cloudEvent.GetStoreName()), + bundleName_(cloudEvent.GetBundleName()) { } @@ -26,11 +32,26 @@ CloudEvent::CloudEvent(int32_t evtId, uint32_t tokenId, std::string storeName, s // return user_; //} +void CloudEvent::SetSchemaKey(std::string schemaKey) +{ + schemaKey_ = schemaKey; +} + +std::string CloudEvent::GetSchemaKey() const +{ + return schemaKey_; +} + std::string CloudEvent::GetBundleName() const { return bundleName_; } +std::string CloudEvent::GetStoreName() const +{ + return storeName_; +} + bool CloudEvent::Equals(const Event &event) const { return false; diff --git a/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_event.h b/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_event.h index ebb1004b..d0d4295b 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_event.h +++ b/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_event.h @@ -25,13 +25,18 @@ public: enum : int32_t { CLOUD_RDB_FEATURE_INIT = EVT_CLOUD, CLOUD_RDB_OPEN_STORE, + CLOUD_RDB_GET_SCHEMA_FINISHED, CLOUD_BUTT }; - CloudEvent(int32_t evtId, uint32_t tokenId, std::string storeName, std::string bundleName); + CloudEvent(int32_t evtId, uint32_t tokenId = 0, std::string storeName = "", std::string bundleName = "", std::string schemaKey = ""); + CloudEvent(int32_t evtId, const CloudEvent &cloudEvent); ~CloudEvent() = default; // int32_t GetUser() const; + void SetSchemaKey(std::string bundleName); + std::string GetSchemaKey() const; std::string GetBundleName() const; + std::string GetStoreName() const; uint32_t GetTokenId() const; bool Equals(const DistributedData::Event &event) const override; @@ -39,7 +44,8 @@ private: // int32_t user_; std::string bundleName_; uint32_t tokenId_; - std::string storeName_ + std::string storeName_; + std::string schemaKey_; }; } // namespace OHOS::DistributedData diff --git a/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.cpp b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.cpp index 82a266a4..740a1ba7 100644 --- a/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.cpp +++ b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.cpp @@ -71,19 +71,23 @@ CloudServiceImpl::CloudServiceImpl() return; } SchemaMeta schemaMeta; - if (!MetaDataManager::GetInstance().LoadMeta(cloudInfo.GetSchemaKey(rdbEvent.GetBundleName()), schemaMeta, - true)) { + std::string schemaKey = cloudInfo.GetSchemaKey(rdbEvent.GetBundleName()); + if (!MetaDataManager::GetInstance().LoadMeta(schemaKey, schemaMeta, true)) { schemaMeta = instance->GetAppSchema(cloudInfo.user, rdbEvent.GetBundleName()); - MetaDataManager::GetInstance().SaveMeta(cloudInfo.GetSchemaKey(rdbEvent.GetBundleName()), schemaMeta, true); + MetaDataManager::GetInstance().SaveMeta(schemaKey, schemaMeta, true); } for (auto &database : schemaMeta.databases) { - if (false) { //TODO:不需要同步 + if (database.name != rdbEvent.GetStoreName() /* ||TODO:不需要同步*/) { continue; } auto cloudDB = instance->ConnectCloudDB(rdbEvent.GetTokenId(), database); //TODO:同步 } + + auto finishedEvent = std::make_unique(CloudEvent::CLOUD_RDB_GET_SCHEMA_FINISHED, rdbEvent); + finishedEvent->SetSchemaKey(schemaKey); + EventCenter::GetInstance().PostEvent(move(finishedEvent)); }); } diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.cpp b/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.cpp index 29ecbddc..839da7c0 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.cpp +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.cpp @@ -79,6 +79,11 @@ RdbServiceImpl::RdbServiceImpl() [this](const std::string& identifier, DistributedDB::AutoLaunchParam ¶m) { return ResolveAutoLaunch(identifier, param); }); + + EventCenter::GetInstance().Subscribe(CloudEvent::CLOUD_RDB_GET_SCHEMA_FINISHED, [this](const Event &event) { + auto &cloudEvent = static_cast(event); + MetaDataManager::GetInstance().LoadMeta() + }); } int32_t RdbServiceImpl::ResolveAutoLaunch(const std::string &identifier, DistributedDB::AutoLaunchParam ¶m) @@ -138,14 +143,14 @@ void RdbServiceImpl::OnClientDied(pid_t pid) }); } -bool RdbServiceImpl::CheckAccess(const RdbSyncerParam ¶m) +bool RdbServiceImpl::CheckAccess(const std::string& bundleName) { auto tokenId = IPCSkeleton::GetCallingTokenID(); - auto instanceId = RdbSyncer::GetInstIndex(tokenId, param.bundleName_); + auto instanceId = RdbSyncer::GetInstIndex(tokenId, bundleName); if (instanceId != 0) { return false; } - return !GetAppId(param.bundleName_).empty(); + return !GetAppId(bundleName).empty(); } std::string RdbServiceImpl::ObtainDistributedTableName(const std::string &device, const std::string &table) @@ -159,16 +164,9 @@ std::string RdbServiceImpl::ObtainDistributedTableName(const std::string &device return DistributedDB::RelationalStoreManager::GetDistributedTableName(uuid, table); } -int32_t OpenStore(const CloudParam &cloudParam) -{ - auto event = - std::make_unique(CloudEvent::CLOUD_RDB_OPEN_STORE, IPCSkeleton::GetCallingTokenID(), cloudParam.storeName, cloudParam.bundleName); - EventCenter::GetInstance().PostEvent(move(event)); -} - -int32_t RdbServiceImpl::InitNotifier(const RdbSyncerParam& param, const sptr notifier) +int32_t RdbServiceImpl::InitNotifier(const std::string& bundleName, const sptr notifier) { - if (!CheckAccess(param)) { + if (!CheckAccess(bundleName)) { ZLOGE("permission error"); return RDB_ERROR; } @@ -286,7 +284,7 @@ std::shared_ptr RdbServiceImpl::GetRdbSyncer(const RdbSyncerParam &pa int32_t RdbServiceImpl::SetDistributedTables(const RdbSyncerParam ¶m, const std::vector &tables) { ZLOGI("enter"); - if (!CheckAccess(param)) { + if (!CheckAccess(param.bundleName_)) { ZLOGE("permission error"); return RDB_ERROR; } @@ -300,7 +298,7 @@ int32_t RdbServiceImpl::SetDistributedTables(const RdbSyncerParam ¶m, const int32_t RdbServiceImpl::DoSync(const RdbSyncerParam ¶m, const SyncOption &option, const RdbPredicates &predicates, SyncResult &result) { - if (!CheckAccess(param)) { + if (!CheckAccess(param.bundleName_)) { ZLOGE("permission error"); return RDB_ERROR; } @@ -323,7 +321,7 @@ void RdbServiceImpl::OnAsyncComplete(pid_t pid, uint32_t seqNum, const SyncResul int32_t RdbServiceImpl::DoAsync(const RdbSyncerParam ¶m, uint32_t seqNum, const SyncOption &option, const RdbPredicates &predicates) { - if (!CheckAccess(param)) { + if (!CheckAccess(param.bundleName_)) { ZLOGE("permission error"); return RDB_ERROR; } @@ -384,7 +382,7 @@ int32_t RdbServiceImpl::DoUnSubscribe(const RdbSyncerParam& param) int32_t RdbServiceImpl::RemoteQuery(const RdbSyncerParam& param, const std::string& device, const std::string& sql, const std::vector& selectionArgs, sptr& resultSet) { - if (!CheckAccess(param)) { + if (!CheckAccess(param.bundleName_)) { ZLOGE("permission error"); return RDB_ERROR; } @@ -408,7 +406,7 @@ std::string RdbServiceImpl::GetAppId(const std::string &bundleName) int32_t RdbServiceImpl::CreateRDBTable( const RdbSyncerParam ¶m, const std::string &writePermission, const std::string &readPermission) { - if (!CheckAccess(param)) { + if (!CheckAccess(param.bundleName_)) { ZLOGE("permission error"); return RDB_ERROR; } @@ -436,7 +434,7 @@ int32_t RdbServiceImpl::CreateRDBTable( int32_t RdbServiceImpl::DestroyRDBTable(const RdbSyncerParam ¶m) { - if (!CheckAccess(param)) { + if (!CheckAccess(param.bundleName_)) { ZLOGE("permission error"); return RDB_ERROR; } @@ -469,4 +467,18 @@ int32_t RdbServiceImpl::OnInitialize() EventCenter::GetInstance().PostEvent(std::move(initEvt)); return RDB_OK; } + +int32_t RdbServiceImpl::OpenStore(const CloudParam &cloudParam) +{ + if (!CheckAccess(cloudParam.bundleName)) { + ZLOGE("permission error"); + return RDB_ERROR; + } + auto event = std::make_unique(CloudEvent::CLOUD_RDB_OPEN_STORE, IPCSkeleton::GetCallingTokenID(), + cloudParam.storeName, cloudParam.bundleName); + EventCenter::GetInstance().PostEvent(move(event)); + + return 0; +} + } // namespace OHOS::DistributedRdb diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.h b/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.h index 7203622e..8d943031 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.h +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.h @@ -41,7 +41,7 @@ public: /* IPC interface */ std::string ObtainDistributedTableName(const std::string& device, const std::string& table) override; - int32_t InitNotifier(const RdbSyncerParam& param, const sptr notifier) override; + int32_t InitNotifier(const std::string& bundleName, const sptr notifier) override; int32_t OpenStore(const CloudParam &cloudParam) override; @@ -74,7 +74,7 @@ protected: private: std::string GenIdentifier(const RdbSyncerParam& param); - bool CheckAccess(const RdbSyncerParam& param); + bool CheckAccess(const std::string& bundleName); void SyncerTimeout(std::shared_ptr syncer); diff --git a/kv_store/frameworks/innerkitsimpl/kvdb/src/dev_manager.cpp b/kv_store/frameworks/innerkitsimpl/kvdb/src/dev_manager.cpp index 76199f4b..93309353 100644 --- a/kv_store/frameworks/innerkitsimpl/kvdb/src/dev_manager.cpp +++ b/kv_store/frameworks/innerkitsimpl/kvdb/src/dev_manager.cpp @@ -77,7 +77,7 @@ void DmDeathCallback::OnRemoteDied() DevManager::DevManager(const std::string &pkgName) : PKG_NAME(pkgName + PKG_NAME_EX) { - RegisterDevCallback(); +// RegisterDevCallback(); } int32_t DevManager::Init() @@ -215,7 +215,7 @@ void DevManager::Offline(const std::string &networkId) deviceInfos_.Delete(deviceInfo.uuid); } ZLOGI("%{public}s observers:%{public}zu", StoreUtil::Anonymous(networkId).c_str(), observers_.Size()); - observers_.ForEach([&networkId](const auto &key, auto &value) { + observers_.ForEachCopies([&networkId](const auto &key, auto &value) { value->Offline(networkId); return false; }); @@ -230,7 +230,7 @@ void DevManager::OnChanged(const std::string &networkId) void DevManager::OnReady(const std::string &networkId) { ZLOGI("%{public}s observers:%{public}zu", StoreUtil::Anonymous(networkId).c_str(), observers_.Size()); - observers_.ForEach([&networkId](const auto &key, auto &value) { + observers_.ForEachCopies([&networkId](const auto &key, auto &value) { value->Online(networkId); return false; }); diff --git a/kv_store/frameworks/jskitsimpl/distributedkvstore/src/js_util.cpp b/kv_store/frameworks/jskitsimpl/distributedkvstore/src/js_util.cpp index d293e93b..4ce4e13c 100644 --- a/kv_store/frameworks/jskitsimpl/distributedkvstore/src/js_util.cpp +++ b/kv_store/frameworks/jskitsimpl/distributedkvstore/src/js_util.cpp @@ -310,7 +310,7 @@ JSUtil::StatusMsg JSUtil::SetValue(napi_env env, const JSUtil::KvStoreVariant& i return SetValue(env, *dblValue, out); } - ZLOGE("napi_value <- KvStoreVariant INVALID value type"); + ZLOGE("napi_value <- KvStoreVariant INVALID value type"); return napi_invalid_arg; } diff --git a/relational_store/frameworks/native/rdb/include/rdb_manager_impl.h b/relational_store/frameworks/native/rdb/include/rdb_manager_impl.h index 13e5ea0b..197f439d 100644 --- a/relational_store/frameworks/native/rdb/include/rdb_manager_impl.h +++ b/relational_store/frameworks/native/rdb/include/rdb_manager_impl.h @@ -39,7 +39,7 @@ public: static RdbManagerImpl &GetInstance(); - int GetRdbService(const RdbSyncerParam& param, std::shared_ptr &service); + int GetRdbService(const std::string& bundleName, std::shared_ptr &service); void OnRemoteDied(); diff --git a/relational_store/frameworks/native/rdb/include/rdb_service_proxy.h b/relational_store/frameworks/native/rdb/include/rdb_service_proxy.h index 50a20253..8fda347e 100644 --- a/relational_store/frameworks/native/rdb/include/rdb_service_proxy.h +++ b/relational_store/frameworks/native/rdb/include/rdb_service_proxy.h @@ -34,8 +34,8 @@ public: std::string ObtainDistributedTableName(const std::string& device, const std::string& table) override; int32_t OpenStore(const CloudParam &cloudParam) override; - int32_t InitNotifier(const RdbSyncerParam& param); - int32_t InitNotifier(const RdbSyncerParam& param, const sptr notifier) override; + int32_t InitNotifier(const std::string& bundleName); + int32_t InitNotifier(const std::string& bundleName, const sptr notifier) override; int32_t SetDistributedTables(const RdbSyncerParam& param, const std::vector& tables) override; diff --git a/relational_store/frameworks/native/rdb/src/rdb_manager.cpp b/relational_store/frameworks/native/rdb/src/rdb_manager.cpp index 261e420f..a9b52b27 100644 --- a/relational_store/frameworks/native/rdb/src/rdb_manager.cpp +++ b/relational_store/frameworks/native/rdb/src/rdb_manager.cpp @@ -19,6 +19,6 @@ namespace OHOS::DistributedRdb { int RdbManager::GetRdbService(const RdbSyncerParam& param, std::shared_ptr &service) { - return RdbManagerImpl::GetInstance().GetRdbService(param, service); + return RdbManagerImpl::GetInstance().GetRdbService(param.bundleName_, service); } } // namespace OHOS::DistributedRdb diff --git a/relational_store/frameworks/native/rdb/src/rdb_manager_impl.cpp b/relational_store/frameworks/native/rdb/src/rdb_manager_impl.cpp index 208c8c21..cfc07cc5 100644 --- a/relational_store/frameworks/native/rdb/src/rdb_manager_impl.cpp +++ b/relational_store/frameworks/native/rdb/src/rdb_manager_impl.cpp @@ -80,7 +80,7 @@ RdbManagerImpl& RdbManagerImpl::GetInstance() return manager; } -int RdbManagerImpl::GetRdbService(const RdbSyncerParam& param, std::shared_ptr &service) +int RdbManagerImpl::GetRdbService(const std::string& bundleName, std::shared_ptr &service) { std::lock_guard lock(mutex_); if (rdbService_ != nullptr) { @@ -101,7 +101,7 @@ int RdbManagerImpl::GetRdbService(const RdbSyncerParam& param, std::shared_ptr serviceProxy = iface_cast(remote); - if (serviceProxy->InitNotifier(param) != RDB_OK) { + if (serviceProxy->InitNotifier(bundleName) != RDB_OK) { ZLOGE("init notifier failed"); return E_ERROR; } @@ -111,7 +111,7 @@ int RdbManagerImpl::GetRdbService(const RdbSyncerParam& param, std::shared_ptr service = nullptr; - int errCode = GetRdbService(param, service); + int errCode = GetRdbService(bundleName_, service); if (errCode != E_OK) { return; } diff --git a/relational_store/frameworks/native/rdb/src/rdb_service_proxy.cpp b/relational_store/frameworks/native/rdb/src/rdb_service_proxy.cpp index 1b0cb411..5c0b93dc 100644 --- a/relational_store/frameworks/native/rdb/src/rdb_service_proxy.cpp +++ b/relational_store/frameworks/native/rdb/src/rdb_service_proxy.cpp @@ -83,7 +83,7 @@ std::string RdbServiceProxy::ObtainDistributedTableName(const std::string &devic return reply.ReadString(); } -int32_t RdbServiceProxy::InitNotifier(const RdbSyncerParam& param) +int32_t RdbServiceProxy::InitNotifier(const std::string& bundleName) { notifier_ = new (std::nothrow) RdbNotifierStub( [this] (uint32_t seqNum, const SyncResult& result) { @@ -98,7 +98,7 @@ int32_t RdbServiceProxy::InitNotifier(const RdbSyncerParam& param) return RDB_ERROR; } - if (InitNotifier(param, notifier_->AsObject().GetRefPtr()) != RDB_OK) { + if (InitNotifier(bundleName, notifier_->AsObject().GetRefPtr()) != RDB_OK) { notifier_ = nullptr; return RDB_ERROR; } @@ -107,13 +107,12 @@ int32_t RdbServiceProxy::InitNotifier(const RdbSyncerParam& param) return RDB_OK; } -int32_t RdbServiceProxy::InitNotifier(const RdbSyncerParam ¶m, const sptr notifier) +int32_t RdbServiceProxy::InitNotifier(const std::string& bundleName, const sptr notifier) { MessageParcel reply; - int32_t status = IPC_SEND(RDB_SERVICE_CMD_INIT_NOTIFIER, reply, param, notifier); + int32_t status = IPC_SEND(RDB_SERVICE_CMD_INIT_NOTIFIER, reply, bundleName, notifier); if (status != RDB_OK) { - ZLOGE("status:%{public}d, bundleName:%{public}s, storeName:%{public}s", - status, param.bundleName_.c_str(), param.storeName_.c_str()); + ZLOGE("status:%{public}d, bundleName:%{public}s", status, bundleName.c_str()); } return status; } diff --git a/relational_store/frameworks/native/rdb/src/rdb_store_config.cpp b/relational_store/frameworks/native/rdb/src/rdb_store_config.cpp index 23b61174..ad764efd 100644 --- a/relational_store/frameworks/native/rdb/src/rdb_store_config.cpp +++ b/relational_store/frameworks/native/rdb/src/rdb_store_config.cpp @@ -391,4 +391,25 @@ void RdbStoreConfig::ClearEncryptKey() { encryptKey_.assign(encryptKey_.size(), 0); } + +void RdbStoreConfig::SetVersion(int32_t version) +{ + schemaVerion_ = version; + +} + +int32_t RdbStoreConfig::GetVersion() const +{ + return schemaVerion_; +} + +void RdbStoreConfig::SetCloudId(std::string cloudId) +{ + cloudId_ = cloudId; +} + +std::string RdbStoreConfig::GetCloudId() const +{ + return cloudId_; +} } // namespace OHOS::NativeRdb diff --git a/relational_store/frameworks/native/rdb/src/rdb_store_impl.cpp b/relational_store/frameworks/native/rdb/src/rdb_store_impl.cpp index 68d48dc0..483be8ce 100644 --- a/relational_store/frameworks/native/rdb/src/rdb_store_impl.cpp +++ b/relational_store/frameworks/native/rdb/src/rdb_store_impl.cpp @@ -89,6 +89,7 @@ int RdbStoreImpl::InnerOpen(const RdbStoreConfig &config) syncerParam_.isEncrypt_ = config.IsEncrypt(); syncerParam_.password_ = {}; // open uri share + if (!config.GetUri().empty()) { std::shared_ptr service = nullptr; errCode = DistributedRdb::RdbManager::GetRdbService(syncerParam_, service); @@ -103,6 +104,22 @@ int RdbStoreImpl::InnerOpen(const RdbStoreConfig &config) } isShared_ = true; } + + if(config.GetVersion() >= 0){ + std::shared_ptr service = nullptr; + errCode = DistributedRdb::RdbManager::GetRdbService(syncerParam_, service); + if (errCode != E_OK) { + LOG_ERROR("RdbStoreImpl::InnerOpen get service failed, err is %{public}d.", errCode); + return E_OK; + } + DistributedRdb::CloudParam cloudParam = { config.GetBundleName(), config.GetName(), config.GetCloudId(), + config.GetVersion() }; + errCode = service->OpenStore(cloudParam); + if (errCode != E_OK) { + LOG_ERROR("RdbStoreImpl::InnerOpen OpenStore failed, err is %{public}d.", errCode); + return E_OK; + } + } #endif return E_OK; } diff --git a/relational_store/frameworks/native/rdb/src/rdb_store_manager.cpp b/relational_store/frameworks/native/rdb/src/rdb_store_manager.cpp index c8e2e8e5..e904bed0 100644 --- a/relational_store/frameworks/native/rdb/src/rdb_store_manager.cpp +++ b/relational_store/frameworks/native/rdb/src/rdb_store_manager.cpp @@ -24,7 +24,7 @@ #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) #include "rdb_security_manager.h" #include "security_policy.h" -#include +//#include #endif namespace OHOS { diff --git a/relational_store/interfaces/inner_api/rdb/include/rdb_service.h b/relational_store/interfaces/inner_api/rdb/include/rdb_service.h index fe89a896..2caa3017 100644 --- a/relational_store/interfaces/inner_api/rdb/include/rdb_service.h +++ b/relational_store/interfaces/inner_api/rdb/include/rdb_service.h @@ -42,8 +42,6 @@ public: }; virtual std::string ObtainDistributedTableName(const std::string &device, const std::string &table) = 0; - virtual int32_t OpenStore(const CloudParam &cloudParam) = 0; - virtual int32_t SetDistributedTables(const RdbSyncerParam ¶m, const std::vector &tables) = 0; virtual int32_t Sync(const RdbSyncerParam ¶m, const SyncOption &option, const RdbPredicates &predicates, @@ -62,7 +60,11 @@ public: virtual int32_t DestroyRDBTable(const RdbSyncerParam ¶m) = 0; - virtual int32_t InitNotifier(const RdbSyncerParam ¶m, const sptr notifier) = 0; + virtual int32_t InitNotifier(const std::string& bundleName, const sptr notifier) = 0; + + virtual int32_t OpenStore(const CloudParam &cloudParam) = 0; + + virtual protected: virtual int32_t DoSync(const RdbSyncerParam ¶m, const SyncOption &option, const RdbPredicates &predicates, diff --git a/relational_store/interfaces/inner_api/rdb/include/rdb_store_config.h b/relational_store/interfaces/inner_api/rdb/include/rdb_store_config.h index 0d7e6709..6bcc799c 100644 --- a/relational_store/interfaces/inner_api/rdb/include/rdb_store_config.h +++ b/relational_store/interfaces/inner_api/rdb/include/rdb_store_config.h @@ -426,6 +426,27 @@ public: * @brief Obtains the encrypt key in this {@code StoreConfig} object. */ std::vector GetEncryptKey() const; + + /** + * @brief Sets the version for the object. + */ + void SetVersion(int32_t version); + + /** + * @brief Obtains the version in this {@code StoreConfig} object. + */ + int32_t GetVersion() const; + + /** + * @brief Sets the cloudId for the object. + */ + void SetCloudId(std::string cloudId); + + /** + * @brief Obtains the cloudId in this {@code StoreConfig} object. + */ + std::string GetCloudId() const; + private: void ClearEncryptKey(); @@ -457,6 +478,11 @@ private: int pageSize; int readConSize_ = 4; std::string encryptAlgo; + + //cloud rdb + std::string cloudId_; + int32_t schemaVerion_ = -1; + }; } // namespace OHOS::NativeRdb -- Gitee From 3593cb6bfbb561fb96ad7ac479eb806240cfe53a Mon Sep 17 00:00:00 2001 From: htt1997 Date: Fri, 21 Apr 2023 11:20:05 +0800 Subject: [PATCH 21/44] update Signed-off-by: htt1997 --- .../native/consumer/src/datashare_helper.cpp | 355 +++++++++--------- .../src/mediadatashare_unit_test.cpp | 96 ++--- .../framework/include/cloud/cloud_event.h | 2 +- .../service/cloud/cloud_service_impl.cpp | 7 +- .../service/rdb/rdb_service_impl.cpp | 35 +- .../service/rdb/rdb_service_impl.h | 4 +- .../service/rdb/rdb_service_stub.cpp | 2 +- .../inner_api/rdb/include/rdb_service.h | 4 +- 8 files changed, 229 insertions(+), 276 deletions(-) diff --git a/data_share/frameworks/native/consumer/src/datashare_helper.cpp b/data_share/frameworks/native/consumer/src/datashare_helper.cpp index d606dfeb..b254599c 100644 --- a/data_share/frameworks/native/consumer/src/datashare_helper.cpp +++ b/data_share/frameworks/native/consumer/src/datashare_helper.cpp @@ -1,17 +1,17 @@ /* - * 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. - */ +* 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 "datashare_helper.h" @@ -21,7 +21,6 @@ #include "dataobs_mgr_client.h" #include "datashare_log.h" #include "datashare_result_set.h" -#include "concurrent_map.h" namespace OHOS { namespace DataShare { @@ -32,23 +31,19 @@ constexpr int INVALID_VALUE = -1; } // namespace class ObserverImpl : public AAFwk::DataAbilityObserverStub { public: - ObserverImpl() : dataShareObserver_(nullptr){}; explicit ObserverImpl(const std::shared_ptr dataShareObserver) : dataShareObserver_(dataShareObserver){}; void OnChange(); void OnChangeExt(const ChangeInfo &info); static DataShareObserver::ChangeInfo ConvertInfo(const AAFwk::ChangeInfo &info); static AAFwk::ChangeInfo ConvertInfo(const DataShareObserver::ChangeInfo &info); - static sptr GetInstance(const std::shared_ptr dataShareObserver, bool remove = false); private: std::shared_ptr dataShareObserver_; - static ConcurrentMap> obs_; }; -ConcurrentMap> ObserverImpl::obs_; -DataShareHelper::DataShareHelper(const sptr &token, const Uri &uri, - std::shared_ptr dataShareConnection) +DataShareHelper::DataShareHelper( + const sptr &token, const Uri &uri, std::shared_ptr dataShareConnection) { LOG_INFO("DataShareHelper::DataShareHelper start"); token_ = token; @@ -71,15 +66,15 @@ DataShareHelper::~DataShareHelper() } /** - * @brief You can use this method to specify the Uri of the data to operate and set the binding relationship - * between the ability using the Data template (data share for short) and the associated client process in - * a DataShareHelper instance. - * - * @param context Indicates the Context object on OHOS. - * @param strUri Indicates the database table or disk file to operate. - * - * @return Returns the created DataShareHelper instance. - */ +* @brief You can use this method to specify the Uri of the data to operate and set the binding relationship +* between the ability using the Data template (data share for short) and the associated client process in +* a DataShareHelper instance. +* +* @param context Indicates the Context object on OHOS. +* @param strUri Indicates the database table or disk file to operate. +* +* @return Returns the created DataShareHelper instance. +*/ std::shared_ptr DataShareHelper::Creator( const std::shared_ptr &context, const std::string &strUri) { @@ -92,15 +87,15 @@ std::shared_ptr DataShareHelper::Creator( } /** - * @brief You can use this method to specify the Uri of the data to operate and set the binding relationship - * between the ability using the Data template (data share for short) and the associated client process in - * a DataShareHelper instance. - * - * @param token Indicates the System token. - * @param strUri Indicates the database table or disk file to operate. - * - * @return Returns the created DataShareHelper instance. - */ +* @brief You can use this method to specify the Uri of the data to operate and set the binding relationship +* between the ability using the Data template (data share for short) and the associated client process in +* a DataShareHelper instance. +* +* @param token Indicates the System token. +* @param strUri Indicates the database table or disk file to operate. +* +* @return Returns the created DataShareHelper instance. +*/ std::shared_ptr DataShareHelper::Creator(const sptr &token, const std::string &strUri) { if (token == nullptr) { @@ -134,11 +129,11 @@ std::shared_ptr DataShareHelper::Creator(const sptr DataShareHelper::GetFileTypes(Uri &uri, const std::string &mimeTypeFilter) { std::vector matchedMIMEs; @@ -177,16 +172,16 @@ std::vector DataShareHelper::GetFileTypes(Uri &uri, const std::stri } /** - * @brief Opens a file in a specified remote path. - * - * @param uri Indicates the path of the file to open. - * @param mode Indicates the file open mode, which can be "r" for read-only access, "w" for write-only access - * (erasing whatever data is currently in the file), "wt" for write access that truncates any existing file, - * "wa" for write-only access to append to any existing data, "rw" for read and write access on any existing data, - * or "rwt" for read and write access that truncates any existing file. - * - * @return Returns the file descriptor. - */ +* @brief Opens a file in a specified remote path. +* +* @param uri Indicates the path of the file to open. +* @param mode Indicates the file open mode, which can be "r" for read-only access, "w" for write-only access +* (erasing whatever data is currently in the file), "wt" for write access that truncates any existing file, +* "wa" for write-only access to append to any existing data, "rw" for read and write access on any existing data, +* or "rwt" for read and write access that truncates any existing file. +* +* @return Returns the file descriptor. +*/ int DataShareHelper::OpenFile(Uri &uri, const std::string &mode) { int fd = INVALID_VALUE; @@ -209,17 +204,17 @@ int DataShareHelper::OpenFile(Uri &uri, const std::string &mode) } /** - * @brief This is like openFile, open a file that need to be able to return sub-sections of files,often assets - * inside of their .hap. - * - * @param uri Indicates the path of the file to open. - * @param mode Indicates the file open mode, which can be "r" for read-only access, "w" for write-only access - * (erasing whatever data is currently in the file), "wt" for write access that truncates any existing file, - * "wa" for write-only access to append to any existing data, "rw" for read and write access on any existing - * data, or "rwt" for read and write access that truncates any existing file. - * - * @return Returns the RawFileDescriptor object containing file descriptor. - */ +* @brief This is like openFile, open a file that need to be able to return sub-sections of files,often assets +* inside of their .hap. +* +* @param uri Indicates the path of the file to open. +* @param mode Indicates the file open mode, which can be "r" for read-only access, "w" for write-only access +* (erasing whatever data is currently in the file), "wt" for write access that truncates any existing file, +* "wa" for write-only access to append to any existing data, "rw" for read and write access on any existing +* data, or "rwt" for read and write access that truncates any existing file. +* +* @return Returns the RawFileDescriptor object containing file descriptor. +*/ int DataShareHelper::OpenRawFile(Uri &uri, const std::string &mode) { int fd = INVALID_VALUE; @@ -242,13 +237,13 @@ int DataShareHelper::OpenRawFile(Uri &uri, const std::string &mode) } /** - * @brief Inserts a single data record into the database. - * - * @param uri Indicates the path of the data to operate. - * @param value Indicates the data record to insert. If this parameter is null, a blank row will be inserted. - * - * @return Returns the index of the inserted data record. - */ +* @brief Inserts a single data record into the database. +* +* @param uri Indicates the path of the data to operate. +* @param value Indicates the data record to insert. If this parameter is null, a blank row will be inserted. +* +* @return Returns the index of the inserted data record. +*/ int DataShareHelper::Insert(Uri &uri, const DataShareValuesBucket &value) { int index = INVALID_VALUE; @@ -271,14 +266,14 @@ int DataShareHelper::Insert(Uri &uri, const DataShareValuesBucket &value) } /** - * @brief Updates data records in the database. - * - * @param uri Indicates the path of data to update. - * @param predicates Indicates filter criteria. You should define the processing logic when this parameter is null. - * @param value Indicates the data to update. This parameter can be null. - * - * @return Returns the number of data records updated. - */ +* @brief Updates data records in the database. +* +* @param uri Indicates the path of data to update. +* @param predicates Indicates filter criteria. You should define the processing logic when this parameter is null. +* @param value Indicates the data to update. This parameter can be null. +* +* @return Returns the number of data records updated. +*/ int DataShareHelper::Update(Uri &uri, const DataSharePredicates &predicates, const DataShareValuesBucket &value) { int index = INVALID_VALUE; @@ -301,13 +296,13 @@ int DataShareHelper::Update(Uri &uri, const DataSharePredicates &predicates, con } /** - * @brief Deletes one or more data records from the database. - * - * @param uri Indicates the path of the data to operate. - * @param predicates Indicates filter criteria. You should define the processing logic when this parameter is null. - * - * @return Returns the number of data records deleted. - */ +* @brief Deletes one or more data records from the database. +* +* @param uri Indicates the path of the data to operate. +* @param predicates Indicates filter criteria. You should define the processing logic when this parameter is null. +* +* @return Returns the number of data records deleted. +*/ int DataShareHelper::Delete(Uri &uri, const DataSharePredicates &predicates) { int index = INVALID_VALUE; @@ -330,14 +325,14 @@ int DataShareHelper::Delete(Uri &uri, const DataSharePredicates &predicates) } /** - * @brief Deletes one or more data records from the database. - * - * @param uri Indicates the path of data to query. - * @param predicates Indicates filter criteria. You should define the processing logic when this parameter is null. - * @param columns Indicates the columns to query. If this parameter is null, all columns are queried. - * - * @return Returns the query result. - */ +* @brief Deletes one or more data records from the database. +* +* @param uri Indicates the path of data to query. +* @param predicates Indicates filter criteria. You should define the processing logic when this parameter is null. +* @param columns Indicates the columns to query. If this parameter is null, all columns are queried. +* +* @return Returns the query result. +*/ std::shared_ptr DataShareHelper::Query(Uri &uri, const DataSharePredicates &predicates, std::vector &columns, DatashareBusinessError *businessError) { @@ -366,13 +361,13 @@ std::shared_ptr DataShareHelper::Query(Uri &uri, const DataS } /** - * @brief Obtains the MIME type matching the data specified by the URI of the data share. This method should be - * implemented by a data share. Data abilities supports general data types, including text, HTML, and JPEG. - * - * @param uri Indicates the URI of the data. - * - * @return Returns the MIME type that matches the data specified by uri. - */ +* @brief Obtains the MIME type matching the data specified by the URI of the data share. This method should be +* implemented by a data share. Data abilities supports general data types, including text, HTML, and JPEG. +* +* @param uri Indicates the URI of the data. +* +* @return Returns the MIME type that matches the data specified by uri. +*/ std::string DataShareHelper::GetType(Uri &uri) { std::string type; @@ -396,13 +391,13 @@ std::string DataShareHelper::GetType(Uri &uri) } /** - * @brief Inserts multiple data records into the database. - * - * @param uri Indicates the path of the data to operate. - * @param values Indicates the data records to insert. - * - * @return Returns the number of data records inserted. - */ +* @brief Inserts multiple data records into the database. +* +* @param uri Indicates the path of the data to operate. +* @param values Indicates the data records to insert. +* +* @return Returns the number of data records inserted. +*/ int DataShareHelper::BatchInsert(Uri &uri, const std::vector &values) { int ret = INVALID_VALUE; @@ -425,11 +420,11 @@ int DataShareHelper::BatchInsert(Uri &uri, const std::vector &dataObserver) { LOG_INFO("Start"); @@ -464,11 +459,11 @@ void DataShareHelper::RegisterObserver(const Uri &uri, const sptr &dataObserver) { LOG_INFO("Start"); @@ -498,10 +493,10 @@ void DataShareHelper::UnregisterObserver(const Uri &uri, const sptr dataObserver, - bool isDescendants) +* Registers an observer to DataObsMgr specified by the given Uri. +* +* @param uri, Indicates the path of the data to operate. +* @param dataObserver, Indicates the DataShareObserver object. +* @param isDescendants, Indicates the Whether to note the change of descendants. +*/ +void DataShareHelper::RegisterObserverExt( + const Uri &uri, std::shared_ptr dataObserver, bool isDescendants) { LOG_INFO("Start"); if (dataObserver == nullptr) { @@ -541,10 +536,9 @@ void DataShareHelper::RegisterObserverExt(const Uri &uri, std::shared_ptr obs(new (std::nothrow) ObserverImpl(dataObserver)); + sptr obs(new (std::nothrow) ObserverImpl(dataObserver)); if (obs == nullptr) { - LOG_ERROR("get ObserverImpl failed"); + LOG_ERROR("new ObserverImpl failed"); return; } ErrCode ret = obsMgrClient->RegisterObserverExt(uri, obs, isDescendants); @@ -555,11 +549,11 @@ void DataShareHelper::RegisterObserverExt(const Uri &uri, std::shared_ptr dataObserver) { LOG_INFO("Start"); @@ -572,9 +566,9 @@ void DataShareHelper::UnregisterObserverExt(const Uri &uri, std::shared_ptr obs(new (std::nothrow) ObserverImpl(dataObserver)); if (obs == nullptr) { - LOG_ERROR("get ObserverImpl failed"); + LOG_ERROR("new ObserverImpl failed"); return; } ErrCode ret = obsMgrClient->UnregisterObserverExt(uri, obs); @@ -585,10 +579,10 @@ void DataShareHelper::UnregisterObserverExt(const Uri &uri, std::shared_ptr ObserverImpl::GetInstance(const std::shared_ptr dataShareObserver, bool remove) -{ - sptr result = nullptr; - obs_.Compute(dataShareObserver.get(), [&result, remove, dataShareObserver](const auto &key, auto &value) { - if (value == nullptr) { - sptr obs(new (std::nothrow) ObserverImpl(dataShareObserver)); - value = obs; - } - result = value; - return !remove && result != nullptr; - }); - - return result; -} - } // namespace DataShare } // namespace OHOS \ No newline at end of file diff --git a/data_share/test/native/unittest/mediadatashare_test/src/mediadatashare_unit_test.cpp b/data_share/test/native/unittest/mediadatashare_test/src/mediadatashare_unit_test.cpp index fe4c5966..7c1569a1 100644 --- a/data_share/test/native/unittest/mediadatashare_test/src/mediadatashare_unit_test.cpp +++ b/data_share/test/native/unittest/mediadatashare_test/src/mediadatashare_unit_test.cpp @@ -1,26 +1,26 @@ /* - * Copyright (C) 2021-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. - */ +* Copyright (C) 2021-2022 Huawei Device Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ #define MLOG_TAG "DataShareUnitTest" #include "mediadatashare_unit_test.h" #include "datashare_helper.h" +#include "datashare_log.h" #include "fetch_result.h" #include "get_self_permissions.h" #include "iservice_registry.h" -#include "datashare_log.h" #include "media_file_utils.h" #include "media_library_manager.h" #include "medialibrary_errno.h" @@ -41,13 +41,13 @@ std::shared_ptr CreateDataShareHelper(int32_t system auto saManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); if (saManager == nullptr) { LOG_ERROR("CreateDataShareHelper::CreateFileExtHelper Get system ability " - "mgr failed."); + "mgr failed."); return nullptr; } auto remoteObj = saManager->GetSystemAbility(systemAbilityId); while (remoteObj == nullptr) { LOG_ERROR("CreateDataShareHelper::CreateFileExtHelper GetSystemAbility " - "Service Failed."); + "Service Failed."); return nullptr; } return DataShare::DataShareHelper::Creator(remoteObj, MEDIALIBRARY_DATA_URI); @@ -202,8 +202,12 @@ void MediaDataShareUnitTest::TearDownTestCase(void) LOG_INFO("TearDownTestCase end"); } -void MediaDataShareUnitTest::SetUp(void) {} -void MediaDataShareUnitTest::TearDown(void) {} +void MediaDataShareUnitTest::SetUp(void) +{ +} +void MediaDataShareUnitTest::TearDown(void) +{ +} HWTEST_F(MediaDataShareUnitTest, MediaDataShare_Predicates_Test_001, TestSize.Level0) { @@ -300,7 +304,7 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_Predicates_Test_006, TestSize.Le vector columns; Uri uri(MEDIALIBRARY_DATA_URI); auto resultSet = helper->Query(uri, predicates, columns); - int result = 0; + int result = -1; if (resultSet != nullptr) { resultSet->GetRowCount(result); } @@ -555,7 +559,7 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_Predicates_Test_021, TestSize.Le LOG_INFO("MediaDataShare_Predicates_Test_021::Start"); DataShare::DataSharePredicates predicates; predicates.EqualTo(MEDIA_DATA_DB_TITLE, "dataShareTest003"); - + std::vector operationItems = predicates.GetOperationList(); DataShare::OperationItem operationItem = operationItems[0]; EXPECT_EQ(operationItem.operation, DataShare::OperationType::EQUAL_TO); @@ -594,7 +598,7 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_Predicates_Test_024, TestSize.Le { LOG_INFO("MediaDataShare_Predicates_Test_024::Start"); DataShare::DataSharePredicates predicates; - int res = predicates.SetWhereArgs(std::vector { "-5" }); + int res = predicates.SetWhereArgs(std::vector{ "-5" }); EXPECT_EQ(res, 0); vector args = predicates.GetWhereArgs(); EXPECT_EQ(args[0], "-5"); @@ -887,7 +891,7 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_ResultSet_Test_003, TestSize.Lev auto resultSet = helper->Query(uri, predicates, columns); AppDataFwk::SharedBlock *block = nullptr; ASSERT_TRUE(resultSet != nullptr); - + bool hasBlock = resultSet->HasBlock(); EXPECT_EQ(hasBlock, true); block = resultSet->GetBlock(); @@ -1071,7 +1075,7 @@ HWTEST_F(MediaDataShareUnitTest, Insert_ConnectionNull_Test_001, TestSize.Level0 valuesBucket.Put(MEDIA_DATA_DB_TITLE, "dataShareTest006"); int value4 = 998; valuesBucket.Put(MEDIA_DATA_DB_PARENT_ID, value4); - auto resultInsert= helper->Insert(uri, valuesBucket); + auto resultInsert = helper->Insert(uri, valuesBucket); EXPECT_EQ(resultInsert, -1); auto resultGetType = helper->GetType(uri); @@ -1124,7 +1128,7 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_NotImplPredicates_Test_001, Test inColumn.push_back("dataShare_Test_001"); inColumn.push_back("dataShare_Test_002"); predicates.In(MEDIA_DATA_DB_TITLE, inColumn); - + vector notInColumn; notInColumn.push_back("dataShare_Test_003"); notInColumn.push_back("dataShare_Test_004"); @@ -1153,7 +1157,7 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_Observer_001, TestSize.Level0) sptr dataObserver; EXPECT_EQ(dataObserver, nullptr); helper->RegisterObserver(uri, dataObserver); - + DataShare::DataShareValuesBucket valuesBucket; valuesBucket.Put(MEDIA_DATA_DB_TITLE, "Datashare_Observer_Test001"); int retVal = helper->Insert(uri, valuesBucket); @@ -1170,9 +1174,9 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_Observer_001, TestSize.Level0) LOG_INFO("MediaDataShare_Observer_001 end"); } -HWTEST_F(MediaDataShareUnitTest, MediaDataShare_RegisterObserverExt_001, TestSize.Level0) +HWTEST_F(MediaDataShareUnitTest, MediaDataShare_ObserverExt_001, TestSize.Level0) { - LOG_INFO("MediaDataShare_RegisterObserverExt_001 start"); + LOG_INFO("MediaDataShare_ObserverExt_001 start"); std::shared_ptr helper = g_mediaDataShareHelper; ASSERT_TRUE(helper != nullptr); Uri uri(MEDIALIBRARY_DATA_URI); @@ -1230,43 +1234,7 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_RegisterObserverExt_001, TestSiz } helper->UnregisterObserverExt(uri, dataObserver); - LOG_INFO("MediaDataShare_RegisterObserverExt_001 end"); -} - -HWTEST_F(MediaDataShareUnitTest, MediaDataShare_UnregisterObserverExt_001, TestSize.Level0) -{ - LOG_INFO("MediaDataShare_UnregisterObserverExt_001 start"); - std::shared_ptr helper = g_mediaDataShareHelper; - ASSERT_TRUE(helper != nullptr); - Uri uri(MEDIALIBRARY_DATA_URI); - std::shared_ptr dataObserver = std::make_shared(); - helper->RegisterObserverExt(uri, dataObserver, true); - - DataShare::DataShareValuesBucket valuesBucket; - valuesBucket.Put(MEDIA_DATA_DB_TITLE, "Datashare_Observer_Test001"); - int retVal = helper->Insert(uri, valuesBucket); - EXPECT_EQ((retVal > 0), true); - helper->NotifyChangeExt({ DataShareObserver::ChangeType::INSERT, { uri } }); - - { - unique_lock lock(dataObserver->mutex_); - if (dataObserver->condition_.wait_for(lock, 2s) == std::cv_status::no_timeout) { - EXPECT_TRUE(true); - } else { - EXPECT_TRUE(false); - } - } - helper->UnregisterObserverExt(uri, dataObserver); - helper->NotifyChangeExt({ DataShareObserver::ChangeType::DELETE, { uri } }); - { - unique_lock lock(dataObserver->mutex_); - if (dataObserver->condition_.wait_for(lock, 2s) == std::cv_status::no_timeout) { - EXPECT_TRUE(false); - } else { - EXPECT_TRUE(true); - } - } - LOG_INFO("MediaDataShare_UnregisterObserverExt_001 end"); + LOG_INFO("MediaDataShare_ObserverExt_001 end"); } } // namespace Media } // namespace OHOS \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_event.h b/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_event.h index d0d4295b..64493501 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_event.h +++ b/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_event.h @@ -25,7 +25,7 @@ public: enum : int32_t { CLOUD_RDB_FEATURE_INIT = EVT_CLOUD, CLOUD_RDB_OPEN_STORE, - CLOUD_RDB_GET_SCHEMA_FINISHED, + CLOUD_RDB_NEED_CREATE, CLOUD_BUTT }; diff --git a/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.cpp b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.cpp index 740a1ba7..35d6ab11 100644 --- a/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.cpp +++ b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.cpp @@ -75,6 +75,9 @@ CloudServiceImpl::CloudServiceImpl() if (!MetaDataManager::GetInstance().LoadMeta(schemaKey, schemaMeta, true)) { schemaMeta = instance->GetAppSchema(cloudInfo.user, rdbEvent.GetBundleName()); MetaDataManager::GetInstance().SaveMeta(schemaKey, schemaMeta, true); + auto finishedEvent = std::make_unique(CloudEvent::CLOUD_RDB_NEED_CREATE, rdbEvent); + finishedEvent->SetSchemaKey(schemaKey); + EventCenter::GetInstance().PostEvent(move(finishedEvent)); } for (auto &database : schemaMeta.databases) { @@ -84,10 +87,6 @@ CloudServiceImpl::CloudServiceImpl() auto cloudDB = instance->ConnectCloudDB(rdbEvent.GetTokenId(), database); //TODO:同步 } - - auto finishedEvent = std::make_unique(CloudEvent::CLOUD_RDB_GET_SCHEMA_FINISHED, rdbEvent); - finishedEvent->SetSchemaKey(schemaKey); - EventCenter::GetInstance().PostEvent(move(finishedEvent)); }); } diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.cpp b/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.cpp index 839da7c0..223a7a09 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.cpp +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.cpp @@ -29,6 +29,7 @@ #include "rdb_notifier_proxy.h" #include "types_export.h" #include "utils/anonymous.h" +#include "cloud/schema_meta.h" using OHOS::DistributedKv::AccountDelegate; using OHOS::DistributedData::CheckerManager; using OHOS::DistributedData::MetaDataManager; @@ -80,9 +81,11 @@ RdbServiceImpl::RdbServiceImpl() return ResolveAutoLaunch(identifier, param); }); - EventCenter::GetInstance().Subscribe(CloudEvent::CLOUD_RDB_GET_SCHEMA_FINISHED, [this](const Event &event) { + EventCenter::GetInstance().Subscribe(CloudEvent::CLOUD_RDB_NEED_CREATE, [this](const Event &event) { auto &cloudEvent = static_cast(event); - MetaDataManager::GetInstance().LoadMeta() + DistributedData::SchemaMeta schemaMeta; + MetaDataManager::GetInstance().LoadMeta(cloudEvent.GetSchemaKey(),schemaMeta); + //CreateDatabase(schemaMeta)TODO:根据schema创建表和trigger }); } @@ -143,14 +146,18 @@ void RdbServiceImpl::OnClientDied(pid_t pid) }); } -bool RdbServiceImpl::CheckAccess(const std::string& bundleName) +bool RdbServiceImpl::CheckAccess(const std::string& bundleName, const std::string& storeName) { - auto tokenId = IPCSkeleton::GetCallingTokenID(); - auto instanceId = RdbSyncer::GetInstIndex(tokenId, bundleName); + CheckerManager::StoreInfo storeInfo; + storeInfo.uid = IPCSkeleton::GetCallingUid(); + storeInfo.tokenId = IPCSkeleton::GetCallingTokenID(); + storeInfo.bundleName = bundleName; + storeInfo.storeId = RdbSyncer::RemoveSuffix(storeName); + auto instanceId = RdbSyncer::GetInstIndex(storeInfo.tokenId, storeInfo.bundleName); if (instanceId != 0) { return false; } - return !GetAppId(bundleName).empty(); + return !CheckerManager::GetInstance().GetAppId(storeInfo).empty(); } std::string RdbServiceImpl::ObtainDistributedTableName(const std::string &device, const std::string &table) @@ -164,9 +171,9 @@ std::string RdbServiceImpl::ObtainDistributedTableName(const std::string &device return DistributedDB::RelationalStoreManager::GetDistributedTableName(uuid, table); } -int32_t RdbServiceImpl::InitNotifier(const std::string& bundleName, const sptr notifier) +int32_t RdbServiceImpl::InitNotifier(const std::string& bundleName, const std::string& storeName,const sptr notifier) { - if (!CheckAccess(bundleName)) { + if (!CheckAccess(bundleName, storeName)) { ZLOGE("permission error"); return RDB_ERROR; } @@ -284,7 +291,7 @@ std::shared_ptr RdbServiceImpl::GetRdbSyncer(const RdbSyncerParam &pa int32_t RdbServiceImpl::SetDistributedTables(const RdbSyncerParam ¶m, const std::vector &tables) { ZLOGI("enter"); - if (!CheckAccess(param.bundleName_)) { + if (!CheckAccess(param.bundleName_, param.storeName_)) { ZLOGE("permission error"); return RDB_ERROR; } @@ -298,7 +305,7 @@ int32_t RdbServiceImpl::SetDistributedTables(const RdbSyncerParam ¶m, const int32_t RdbServiceImpl::DoSync(const RdbSyncerParam ¶m, const SyncOption &option, const RdbPredicates &predicates, SyncResult &result) { - if (!CheckAccess(param.bundleName_)) { + if (!CheckAccess(param.bundleName_, param.storeName_)) { ZLOGE("permission error"); return RDB_ERROR; } @@ -321,7 +328,7 @@ void RdbServiceImpl::OnAsyncComplete(pid_t pid, uint32_t seqNum, const SyncResul int32_t RdbServiceImpl::DoAsync(const RdbSyncerParam ¶m, uint32_t seqNum, const SyncOption &option, const RdbPredicates &predicates) { - if (!CheckAccess(param.bundleName_)) { + if (!CheckAccess(param.bundleName_, param.storeName_)) { ZLOGE("permission error"); return RDB_ERROR; } @@ -382,7 +389,7 @@ int32_t RdbServiceImpl::DoUnSubscribe(const RdbSyncerParam& param) int32_t RdbServiceImpl::RemoteQuery(const RdbSyncerParam& param, const std::string& device, const std::string& sql, const std::vector& selectionArgs, sptr& resultSet) { - if (!CheckAccess(param.bundleName_)) { + if (!CheckAccess(param.bundleName_, param.storeName_)) { ZLOGE("permission error"); return RDB_ERROR; } @@ -406,7 +413,7 @@ std::string RdbServiceImpl::GetAppId(const std::string &bundleName) int32_t RdbServiceImpl::CreateRDBTable( const RdbSyncerParam ¶m, const std::string &writePermission, const std::string &readPermission) { - if (!CheckAccess(param.bundleName_)) { + if (!CheckAccess(param.bundleName_, param.storeName_)) { ZLOGE("permission error"); return RDB_ERROR; } @@ -434,7 +441,7 @@ int32_t RdbServiceImpl::CreateRDBTable( int32_t RdbServiceImpl::DestroyRDBTable(const RdbSyncerParam ¶m) { - if (!CheckAccess(param.bundleName_)) { + if (!CheckAccess(param.bundleName_, param.storeName_)) { ZLOGE("permission error"); return RDB_ERROR; } diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.h b/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.h index 8d943031..a1b4acc0 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.h +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.h @@ -41,7 +41,7 @@ public: /* IPC interface */ std::string ObtainDistributedTableName(const std::string& device, const std::string& table) override; - int32_t InitNotifier(const std::string& bundleName, const sptr notifier) override; + int32_t InitNotifier(const std::string& bundleName, const std::string& storeName, const sptr notifier) override; int32_t OpenStore(const CloudParam &cloudParam) override; @@ -74,7 +74,7 @@ protected: private: std::string GenIdentifier(const RdbSyncerParam& param); - bool CheckAccess(const std::string& bundleName); + bool CheckAccess(const std::string& bundleName, const std::string& storeName); void SyncerTimeout(std::shared_ptr syncer); diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_stub.cpp b/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_stub.cpp index 67885150..6438028b 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_stub.cpp +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_stub.cpp @@ -63,7 +63,7 @@ int32_t RdbServiceStub::OnRemoteInitNotifier(MessageParcel &data, MessageParcel param.storeName_.c_str()); return IPC_STUB_INVALID_DATA_ERR; } - auto status = InitNotifier(param, notifier); + auto status = InitNotifier(param.bundleName_, notifier); if (!ITypesUtil::Marshal(reply, status)) { ZLOGE("Marshal status:0x%{public}x", status); return IPC_STUB_WRITE_PARCEL_ERR; diff --git a/relational_store/interfaces/inner_api/rdb/include/rdb_service.h b/relational_store/interfaces/inner_api/rdb/include/rdb_service.h index 2caa3017..d549cb3a 100644 --- a/relational_store/interfaces/inner_api/rdb/include/rdb_service.h +++ b/relational_store/interfaces/inner_api/rdb/include/rdb_service.h @@ -60,12 +60,10 @@ public: virtual int32_t DestroyRDBTable(const RdbSyncerParam ¶m) = 0; - virtual int32_t InitNotifier(const std::string& bundleName, const sptr notifier) = 0; + virtual int32_t InitNotifier(const std::string& bundleName, const std::string& storeName, const sptr notifier) = 0; virtual int32_t OpenStore(const CloudParam &cloudParam) = 0; - virtual - protected: virtual int32_t DoSync(const RdbSyncerParam ¶m, const SyncOption &option, const RdbPredicates &predicates, SyncResult &result) = 0; -- Gitee From 142c824f433868cade13f50ad8294fb05c333329 Mon Sep 17 00:00:00 2001 From: htt1997 Date: Fri, 21 Apr 2023 14:35:49 +0800 Subject: [PATCH 22/44] fix Signed-off-by: htt1997 --- .../service/rdb/rdb_service_impl.cpp | 8 ++++---- .../service/rdb/rdb_service_impl.h | 6 +++--- .../service/rdb/rdb_service_stub.cpp | 10 +++++----- .../native/rdb/include/rdb_manager_impl.h | 2 +- .../native/rdb/include/rdb_service_proxy.h | 3 ++- .../frameworks/native/rdb/src/rdb_manager.cpp | 4 ++-- .../native/rdb/src/rdb_manager_impl.cpp | 6 +++--- .../native/rdb/src/rdb_service_proxy.cpp | 15 ++++++--------- .../inner_api/rdb/include/rdb_service.h | 3 ++- 9 files changed, 28 insertions(+), 29 deletions(-) diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.cpp b/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.cpp index 54f6dcba..abb4f694 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.cpp +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.cpp @@ -171,9 +171,9 @@ std::string RdbServiceImpl::ObtainDistributedTableName(const std::string &device return DistributedDB::RelationalStoreManager::GetDistributedTableName(uuid, table); } -int32_t RdbServiceImpl::InitNotifier(const std::string& bundleName, const std::string& storeName,const sptr notifier) +int32_t RdbServiceImpl::InitNotifier(const std::string &bundleName, const sptr notifier) { - if (!CheckAccess(bundleName, storeName)) { + if (!CheckAccess(bundleName, "")) { ZLOGE("permission error"); return RDB_ERROR; } @@ -182,7 +182,7 @@ int32_t RdbServiceImpl::InitNotifier(const std::string& bundleName, const std::s return RDB_ERROR; } pid_t pid = IPCSkeleton::GetCallingPid(); - auto recipient = new(std::nothrow) DeathRecipientImpl([this, pid] { + auto recipient = new (std::nothrow) DeathRecipientImpl([this, pid] { OnClientDied(pid); }); if (recipient == nullptr) { @@ -471,7 +471,7 @@ int32_t RdbServiceImpl::OnInitialize() int32_t RdbServiceImpl::OpenStore(const CloudParam &cloudParam) { - if (!CheckAccess(cloudParam.bundleName)) { + if (!CheckAccess(cloudParam.bundleName, cloudParam.storeName)) { ZLOGE("permission error"); return RDB_ERROR; } diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.h b/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.h index de9a76dc..17e12968 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.h +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.h @@ -41,9 +41,7 @@ public: /* IPC interface */ std::string ObtainDistributedTableName(const std::string& device, const std::string& table) override; - int32_t InitNotifier(const std::string& bundleName, const std::string& storeName, const sptr notifier) override; - - int32_t OpenStore(const CloudParam &cloudParam) override; + int32_t InitNotifier(const std::string& bundleName, const sptr notifier) override; int32_t SetDistributedTables(const RdbSyncerParam& param, const std::vector& tables) override; @@ -60,6 +58,8 @@ public: int32_t OnInitialize() override; + int32_t OpenStore(const CloudParam &cloudParam) override; + protected: int32_t DoSync(const RdbSyncerParam& param, const SyncOption& option, const RdbPredicates& predicates, SyncResult& result) override; diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_stub.cpp b/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_stub.cpp index 6438028b..83d11cdb 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_stub.cpp +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_stub.cpp @@ -56,14 +56,14 @@ int32_t RdbServiceStub::OnOpenStore(MessageParcel &data, MessageParcel &reply) { int32_t RdbServiceStub::OnRemoteInitNotifier(MessageParcel &data, MessageParcel &reply) { - RdbSyncerParam param; + std::string bundleName; sptr notifier; - if (!ITypesUtil::Unmarshal(data, param, notifier) || notifier == nullptr) { - ZLOGE("Unmarshal bundleName_:%{public}s storeName_:%{public}s", param.bundleName_.c_str(), - param.storeName_.c_str()); + if (!ITypesUtil::Unmarshal(data, bundleName, notifier) || bundleName.empty() || notifier == nullptr) { + ZLOGE("Unmarshal bundleName:%{public}s notifier is nullptr:%{public}d", bundleName.c_str(), + notifier == nullptr); return IPC_STUB_INVALID_DATA_ERR; } - auto status = InitNotifier(param.bundleName_, notifier); + auto status = InitNotifier(bundleName, notifier); if (!ITypesUtil::Marshal(reply, status)) { ZLOGE("Marshal status:0x%{public}x", status); return IPC_STUB_WRITE_PARCEL_ERR; diff --git a/relational_store/frameworks/native/rdb/include/rdb_manager_impl.h b/relational_store/frameworks/native/rdb/include/rdb_manager_impl.h index 197f439d..80689b3d 100644 --- a/relational_store/frameworks/native/rdb/include/rdb_manager_impl.h +++ b/relational_store/frameworks/native/rdb/include/rdb_manager_impl.h @@ -39,7 +39,7 @@ public: static RdbManagerImpl &GetInstance(); - int GetRdbService(const std::string& bundleName, std::shared_ptr &service); + int GetRdbService(const std::string& bundleName, const std::string& storeName, std::shared_ptr &service); void OnRemoteDied(); diff --git a/relational_store/frameworks/native/rdb/include/rdb_service_proxy.h b/relational_store/frameworks/native/rdb/include/rdb_service_proxy.h index 8fda347e..43099c5a 100644 --- a/relational_store/frameworks/native/rdb/include/rdb_service_proxy.h +++ b/relational_store/frameworks/native/rdb/include/rdb_service_proxy.h @@ -33,7 +33,6 @@ public: std::string ObtainDistributedTableName(const std::string& device, const std::string& table) override; - int32_t OpenStore(const CloudParam &cloudParam) override; int32_t InitNotifier(const std::string& bundleName); int32_t InitNotifier(const std::string& bundleName, const sptr notifier) override; @@ -57,6 +56,8 @@ public: void ImportObservers(ObserverMap& observers); + /*CLoudData*/ + int32_t OpenStore(const CloudParam &cloudParam) override; protected: int32_t DoSync(const RdbSyncerParam& param, const SyncOption& option, const RdbPredicates& predicates, SyncResult& result) override; diff --git a/relational_store/frameworks/native/rdb/src/rdb_manager.cpp b/relational_store/frameworks/native/rdb/src/rdb_manager.cpp index a9b52b27..6dc545b8 100644 --- a/relational_store/frameworks/native/rdb/src/rdb_manager.cpp +++ b/relational_store/frameworks/native/rdb/src/rdb_manager.cpp @@ -17,8 +17,8 @@ #include "rdb_manager_impl.h" namespace OHOS::DistributedRdb { -int RdbManager::GetRdbService(const RdbSyncerParam& param, std::shared_ptr &service) +int RdbManager::GetRdbService(const RdbSyncerParam ¶m, std::shared_ptr &service) { - return RdbManagerImpl::GetInstance().GetRdbService(param.bundleName_, service); + return RdbManagerImpl::GetInstance().GetRdbService(param.bundleName_, param.storeName_, service); } } // namespace OHOS::DistributedRdb diff --git a/relational_store/frameworks/native/rdb/src/rdb_manager_impl.cpp b/relational_store/frameworks/native/rdb/src/rdb_manager_impl.cpp index cfc07cc5..3fc093dd 100644 --- a/relational_store/frameworks/native/rdb/src/rdb_manager_impl.cpp +++ b/relational_store/frameworks/native/rdb/src/rdb_manager_impl.cpp @@ -80,7 +80,7 @@ RdbManagerImpl& RdbManagerImpl::GetInstance() return manager; } -int RdbManagerImpl::GetRdbService(const std::string& bundleName, std::shared_ptr &service) +int RdbManagerImpl::GetRdbService(const std::string& bundleName, const std::string& storeName, std::shared_ptr &service) { std::lock_guard lock(mutex_); if (rdbService_ != nullptr) { @@ -101,7 +101,7 @@ int RdbManagerImpl::GetRdbService(const std::string& bundleName, std::shared_ptr return E_NOT_SUPPORTED; } sptr serviceProxy = iface_cast(remote); - if (serviceProxy->InitNotifier(bundleName) != RDB_OK) { + if (serviceProxy->InitNotifier(bundleName, storeName) != RDB_OK) { ZLOGE("init notifier failed"); return E_ERROR; } @@ -131,7 +131,7 @@ void RdbManagerImpl::OnRemoteDied() RdbSyncerParam param; param.bundleName_ = bundleName_; std::shared_ptr service = nullptr; - int errCode = GetRdbService(bundleName_, service); + int errCode = GetRdbService(bundleName_, "", service); if (errCode != E_OK) { return; } diff --git a/relational_store/frameworks/native/rdb/src/rdb_service_proxy.cpp b/relational_store/frameworks/native/rdb/src/rdb_service_proxy.cpp index 5c0b93dc..04388259 100644 --- a/relational_store/frameworks/native/rdb/src/rdb_service_proxy.cpp +++ b/relational_store/frameworks/native/rdb/src/rdb_service_proxy.cpp @@ -83,16 +83,13 @@ std::string RdbServiceProxy::ObtainDistributedTableName(const std::string &devic return reply.ReadString(); } -int32_t RdbServiceProxy::InitNotifier(const std::string& bundleName) +int32_t RdbServiceProxy::InitNotifier(const std::string &bundleName) { - notifier_ = new (std::nothrow) RdbNotifierStub( - [this] (uint32_t seqNum, const SyncResult& result) { - OnSyncComplete(seqNum, result); - }, - [this] (const std::string& storeName, const std::vector& devices) { - OnDataChange(storeName, devices); - } - ); + notifier_ = new (std::nothrow) + RdbNotifierStub([this](uint32_t seqNum, const SyncResult &result) { OnSyncComplete(seqNum, result); }, + [this](const std::string &storeName, const std::vector &devices) { + OnDataChange(storeName, devices); + }); if (notifier_ == nullptr) { ZLOGE("create notifier failed"); return RDB_ERROR; diff --git a/relational_store/interfaces/inner_api/rdb/include/rdb_service.h b/relational_store/interfaces/inner_api/rdb/include/rdb_service.h index d549cb3a..9e1699be 100644 --- a/relational_store/interfaces/inner_api/rdb/include/rdb_service.h +++ b/relational_store/interfaces/inner_api/rdb/include/rdb_service.h @@ -60,8 +60,9 @@ public: virtual int32_t DestroyRDBTable(const RdbSyncerParam ¶m) = 0; - virtual int32_t InitNotifier(const std::string& bundleName, const std::string& storeName, const sptr notifier) = 0; + virtual int32_t InitNotifier(const std::string& bundleName, const sptr notifier) = 0; + /*Cloud Data*/ virtual int32_t OpenStore(const CloudParam &cloudParam) = 0; protected: -- Gitee From 53815d325dc4f2912813879c86787b7c9ed4565c Mon Sep 17 00:00:00 2001 From: Sven Wang Date: Fri, 21 Apr 2023 15:13:50 +0800 Subject: [PATCH 23/44] update Signed-off-by: Sven Wang --- .../framework/include/store/auto_cache.h | 2 +- .../framework/include/store/general_store.h | 7 +- .../framework/include/store/general_value.h | 49 ++-- .../framework/store/auto_cache.cpp | 2 +- .../service/rdb/rdb_general_store.cpp | 220 ++++++++++++++++++ .../service/rdb/rdb_general_store.h | 60 +++++ .../service/rdb/rdb_service_impl.cpp | 5 + kv_store/frameworks/common/traits.h | 92 ++++++++ .../native/rdb/src/rdb_store_manager.cpp | 1 - .../inner_api/rdb/include/asset_value.h | 4 +- .../inner_api/rdb/include/value_object.h | 109 ++++----- .../rdb/unittest/rdb_value_bucket_test.cpp | 2 +- 12 files changed, 459 insertions(+), 94 deletions(-) create mode 100644 datamgr_service/services/distributeddataservice/service/rdb/rdb_general_store.cpp create mode 100644 datamgr_service/services/distributeddataservice/service/rdb/rdb_general_store.h create mode 100644 kv_store/frameworks/common/traits.h diff --git a/datamgr_service/services/distributeddataservice/framework/include/store/auto_cache.h b/datamgr_service/services/distributeddataservice/framework/include/store/auto_cache.h index 8d86bddb..3476e23f 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/store/auto_cache.h +++ b/datamgr_service/services/distributeddataservice/framework/include/store/auto_cache.h @@ -35,7 +35,7 @@ public: using Executor = ExecutorPool; using TaskId = ExecutorPool::TaskId; using Creator = std::function; - static AutoCache &Instance(); + static AutoCache &GetInstance(); int32_t RegCreator(int32_t type, Creator creator); void Bind(std::shared_ptr executor); Store GetStore(const StoreMetaData &meta, const Watchers &watchers); diff --git a/datamgr_service/services/distributeddataservice/framework/include/store/general_store.h b/datamgr_service/services/distributeddataservice/framework/include/store/general_store.h index f6598661..d2006b5b 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/store/general_store.h +++ b/datamgr_service/services/distributeddataservice/framework/include/store/general_store.h @@ -16,7 +16,7 @@ #ifndef OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_STORE_GENERAL_STORE_H #define OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_STORE_GENERAL_STORE_H #include - +#include #include "store/cursor.h" #include "store/general_value.h" #include "store/general_watcher.h" @@ -24,6 +24,9 @@ namespace OHOS::DistributedData { class GeneralStore { public: using Watcher = GeneralWatcher; + using Async = std::function>)>; + using Devices = std::vector; + virtual ~GeneralStore() = default; virtual int32_t Close() = 0; virtual int32_t Execute(const std::string &table, const std::string &sql) = 0; @@ -35,6 +38,8 @@ public: virtual std::shared_ptr Query(const std::string &table, const std::string &sql, Values &&args) = 0; virtual int32_t Watch(int32_t origin, Watcher &watcher) = 0; virtual int32_t Unwatch(int32_t origin, Watcher &watcher) = 0; + virtual int32_t Sync(const Devices &devices, int32_t mode, const GenQuery &query, Async async) = 0; + virtual int32_t Sync(const Devices &devices, int32_t mode, const GenQuery &query, Async async, bool wait) = 0; }; } // namespace OHOS::DistributedData #endif // OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_STORE_GENERAL_STORE_H diff --git a/datamgr_service/services/distributeddataservice/framework/include/store/general_value.h b/datamgr_service/services/distributeddataservice/framework/include/store/general_value.h index 58a4547e..a3acb79f 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/store/general_value.h +++ b/datamgr_service/services/distributeddataservice/framework/include/store/general_value.h @@ -16,10 +16,11 @@ #ifndef OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_STORE_GENERAL_VALUE_H #define OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_STORE_GENERAL_VALUE_H #include +#include #include -#include #include #include +#include "traits.h" namespace OHOS::DistributedData { enum GeneralError : int32_t { @@ -33,6 +34,7 @@ enum GeneralError : int32_t E_ALREADY_CLOSED, E_BUTT, }; + struct Asset { uint32_t version; std::string name; @@ -42,52 +44,45 @@ struct Asset { std::string size; std::string hash; }; + +struct GenQuery { + virtual ~GenQuery() = default; + virtual int32_t GetInterfaceId() = 0; +}; + using Assets = std::vector; using Bytes = std::vector; using Value = std::variant; using Values = std::vector; using VBucket = std::map; using VBuckets = std::vector; -template -inline constexpr size_t TYPE_INDEX = - std::__detail::__variant::__index_of_v; - -template -inline constexpr size_t index_of_v = std::__detail::__variant::__index_of_v<_Tp, _Types...>; -template -std::enable_if_t<(index_of_v<_T, _Rest...> < sizeof...(_Rest)), const _T *> GetIf(const std::variant<_Rest...> &input) -{ - return std::get_if<_T>(&input); -} +template +inline constexpr size_t TYPE_INDEX = Traits::variant_index_of_v; -template -std::enable_if_t<(index_of_v<_T, _Rest...> >= sizeof...(_Rest)), const _T *> GetIf(const std::variant<_Rest...> &input) -{ - return nullptr; -} +inline constexpr size_t TYPE_MAX = Traits::variant_size_of_v; -template -bool Get(const _T &input, _O &output) +template +bool GetItem(const T &input, O &output) { return false; } -template -bool Get(const _T &input, _O &output) +template +bool GetItem(const T &input, O &output) { - const _First *val = GetIf<_First>(input); + auto val = Traits::get_if(&input); if (val != nullptr) { output = *val; return true; } - return Get<_T, _O, _Rest...>(input, output); + return GetItem(input, output); } -template -bool Convert(const _T &input, std::variant<_Rest...> &output) +template +bool Convert(const T &input, std::variant &output) { - return Get<_T, decltype(output), _Rest...>(input, output); -} + return GetItem(input, output); } +} // namespace OHOS::DistributedData #endif // OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_STORE_GENERAL_VALUE_H diff --git a/datamgr_service/services/distributeddataservice/framework/store/auto_cache.cpp b/datamgr_service/services/distributeddataservice/framework/store/auto_cache.cpp index 84c768d0..a488709a 100644 --- a/datamgr_service/services/distributeddataservice/framework/store/auto_cache.cpp +++ b/datamgr_service/services/distributeddataservice/framework/store/auto_cache.cpp @@ -17,7 +17,7 @@ #include namespace OHOS::DistributedData { -AutoCache &AutoCache::Instance() +AutoCache &AutoCache::GetInstance() { static AutoCache cache; return cache; diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_general_store.cpp b/datamgr_service/services/distributeddataservice/service/rdb/rdb_general_store.cpp new file mode 100644 index 00000000..8d5faf4b --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_general_store.cpp @@ -0,0 +1,220 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#define LOG_TAG "RdbGeneralStore" +#include "rdb_general_store.h" +#include "crypto_manager.h" +#include "log_print.h" +#include "metadata/meta_data_manager.h" +#include "metadata/secret_key_meta_data.h" +#include "rdb_helper.h" +#include "relational_store_manager.h" +namespace OHOS::DistributedRdb { +using namespace DistributedData; +using namespace OHOS::NativeRdb; +class RdbOpenCallbackImpl : public RdbOpenCallback { +public: + int OnCreate(RdbStore &rdbStore) override + { + return NativeRdb::E_OK; + } + int OnUpgrade(RdbStore &rdbStore, int oldVersion, int newVersion) override + { + return NativeRdb::E_OK; + } +}; +RdbGeneralStore::RdbGeneralStore(const StoreMetaData &meta) : manager_(meta.appId, meta.user, meta.instanceId) +{ + DistributedDB::RelationalStoreDelegate::Option option; + if (meta.isEncrypt) { + std::string key = meta.GetSecretKey(); + SecretKeyMetaData secretKeyMeta; + MetaDataManager::GetInstance().LoadMeta(key, secretKeyMeta, true); + std::vector decryptKey; + CryptoManager::GetInstance().Decrypt(secretKeyMeta.sKey, decryptKey); + if (option.passwd.SetValue(decryptKey.data(), decryptKey.size()) != DistributedDB::CipherPassword::OK) { + std::fill(decryptKey.begin(), decryptKey.end(), 0); + } + std::fill(decryptKey.begin(), decryptKey.end(), 0); + option.isEncryptedDb = meta.isEncrypt; + option.iterateTimes = 10000; + option.cipher = DistributedDB::CipherType::AES_256_GCM; + } + option.observer = nullptr; + manager_.OpenStore(meta.dataDir, meta.storeId, option, delegate_); + RdbStoreConfig config(meta.dataDir); + config.SetCreateNecessary(false); + RdbOpenCallbackImpl callback; + int32_t errCode = NativeRdb::E_OK; + store_ = RdbHelper::GetRdbStore(config, meta.version, callback, errCode); + if (errCode != NativeRdb::E_OK) { + ZLOGE("GetRdbStore failed, errCode is %{public}d, storeId is %{public}s", errCode, meta.storeId.c_str()); + } +} + +int32_t RdbGeneralStore::Close() +{ + manager_.CloseStore(delegate_); + delegate_ = nullptr; + store_ = nullptr; + return 0; +} + +int32_t RdbGeneralStore::Execute(const std::string &table, const std::string &sql) +{ + auto ret = store_->ExecuteSql(sql); + if (ret == NativeRdb::E_OK) { + return GeneralError::E_OK; + } + return GeneralError::E_ERROR; +} + +int32_t RdbGeneralStore::Insert(const std::string &table, VBucket &&values) +{ + ValuesBucket rdbVBucket; + for (auto &[key, value] : values) { + rdbVBucket.Put(key, Convert(std::move(value))); + } + int64_t outRowId; + auto ret = store_->Insert(outRowId, table, std::move(rdbVBucket)); + if (ret == NativeRdb::E_OK) { + return GeneralError::E_OK; + } + return GeneralError::E_ERROR; +} +int32_t RdbGeneralStore::BatchInsert(const std::string &table, VBuckets &&values) +{ + return 0; +} +int32_t RdbGeneralStore::Update(const std::string &table, const std::string &sql, VBucket &&values) +{ + return 0; +} +int32_t RdbGeneralStore::BatchUpdate(const std::string &table, const std::string &sql, VBuckets &&values) +{ + return 0; +} +int32_t RdbGeneralStore::Delete(const std::string &table, const std::string &sql, Values &&args) +{ + return 0; +} +std::shared_ptr RdbGeneralStore::Query(const std::string &table, const std::string &sql, Values &&args) +{ + return std::shared_ptr(); +} +int32_t RdbGeneralStore::Watch(int32_t origin, Watcher &watcher) +{ + return 0; +} +int32_t RdbGeneralStore::Unwatch(int32_t origin, Watcher &watcher) +{ + return 0; +} +int32_t RdbGeneralStore::Sync(const Devices &devices, int32_t mode, const GenQuery &query, Async async) +{ + return 0; +} +int32_t RdbGeneralStore::Sync(const Devices &devices, int32_t mode, const GenQuery &query, Async async, bool wait) +{ + return 0; +} + +NativeRdb::ValueObject RdbGeneralStore::Convert(Value &&value) +{ + ValueObject rdbValue; + if (DistributedData::Convert(rdbValue.value, value)) { + return rdbValue; + } + if (value.index() == TYPE_INDEX) { + auto *asset = Traits::get_if(&value); + if (asset == nullptr) { + return NativeRdb::ValueObject(); + } + AssetValue assetValue; + assetValue.version = asset->version; + assetValue.name = asset->name; + assetValue.uri = asset->uri; + assetValue.createTime = asset->createTime; + assetValue.modifyTime = asset->modifyTime; + assetValue.size = asset->size; + assetValue.hash = asset->hash; + return std::move(assetValue); + } + + if (value.index() == TYPE_INDEX) { + auto *assets = Traits::get_if(&value); + if (assets == nullptr) { + return NativeRdb::ValueObject(); + } + std::vector assetsValue; + for (auto &asset : *assets) { + AssetValue assetValue; + assetValue.version = asset.version; + assetValue.name = asset.name; + assetValue.uri = asset.uri; + assetValue.createTime = asset.createTime; + assetValue.modifyTime = asset.modifyTime; + assetValue.size = asset.size; + assetValue.hash = asset.hash; + assetsValue.push_back(std::move(assetValue)); + } + return std::move(assetsValue); + } + return NativeRdb::ValueObject(); +} +DistributedData::Value RdbGeneralStore::Convert(ValueObject &&rdbValue) +{ + DistributedData::Value value; + if (DistributedData::Convert(rdbValue.value, value)) { + return value; + } + if (rdbValue.value.index() == Traits::variant_index_of_v) { + auto *rdbAsset = Traits::get_if(&rdbValue.value); + if (rdbAsset == nullptr) { + return {}; + } + value = Asset{ + .version = rdbAsset->version, + .name = rdbAsset->name, + .uri = rdbAsset->uri, + .createTime = rdbAsset->createTime, + .modifyTime = rdbAsset->modifyTime, + .size = rdbAsset->size, + .hash = rdbAsset->hash + }; + return value; + } + + if (rdbValue.value.index() == Traits::variant_index_of_v) { + auto *rdbAssets = Traits::get_if(&value); + if (rdbAssets == nullptr) { + return value; + } + Assets assets; + for (auto &rdbAsset : *rdbAssets) { + assets.push_back(Asset{ + .version = rdbAsset.version, + .name = rdbAsset.name, + .uri = rdbAsset.uri, + .createTime = rdbAsset.createTime, + .modifyTime = rdbAsset.modifyTime, + .size = rdbAsset.size, + .hash = rdbAsset.hash + }); + } + return std::move(assets); + } + return value; +} +} // namespace OHOS::DistributedRdb diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_general_store.h b/datamgr_service/services/distributeddataservice/service/rdb/rdb_general_store.h new file mode 100644 index 00000000..bfd63652 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_general_store.h @@ -0,0 +1,60 @@ +/* + * 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_DISTRIBUTED_DATA_DATAMGR_SERVICE_RDB_RDB_GENERAL_STORE_H +#define OHOS_DISTRIBUTED_DATA_DATAMGR_SERVICE_RDB_RDB_GENERAL_STORE_H +#include +#include "relational_store_delegate.h" +#include "relational_store_manager.h" + +#include "rdb_store.h" +#include "store/general_store.h" +#include "metadata/store_meta_data.h" +namespace OHOS::DistributedRdb { +class RdbGeneralStore : public DistributedData::GeneralStore { +public: + using Cursor = DistributedData::Cursor; + using GenQuery = DistributedData::GenQuery; + using VBucket = DistributedData::VBucket; + using VBuckets = DistributedData::VBuckets; + using Values = DistributedData::Values; + using StoreMetaData = DistributedData::StoreMetaData; + using RdbStore = OHOS::NativeRdb::RdbStore; + using RdbDelegate = DistributedDB::RelationalStoreDelegate; + using RdbManager = DistributedDB::RelationalStoreManager; + RdbGeneralStore(const StoreMetaData &metaData); + int32_t Close() override; + int32_t Execute(const std::string &table, const std::string &sql) override; + int32_t Insert(const std::string &table, VBucket &&values) override; + int32_t BatchInsert(const std::string &table, VBuckets &&values) override; + int32_t Update(const std::string &table, const std::string &sql, VBucket &&values) override; + int32_t BatchUpdate(const std::string &table, const std::string &sql, VBuckets &&values) override; + int32_t Delete(const std::string &table, const std::string &sql, Values &&args) override; + std::shared_ptr Query(const std::string &table, const std::string &sql, Values &&args) override; + int32_t Watch(int32_t origin, Watcher &watcher) override; + int32_t Unwatch(int32_t origin, Watcher &watcher) override; + int32_t Sync(const Devices &devices, int32_t mode, const GenQuery &query, Async async) override; + int32_t Sync(const Devices &devices, int32_t mode, const GenQuery &query, Async async, bool wait) override; + +private: + NativeRdb::ValueObject Convert(DistributedData::Value &&value); + DistributedData::Value Convert(NativeRdb::ValueObject &&rdbValue); + + RdbManager manager_; + RdbDelegate *delegate_ = nullptr; + std::shared_ptr store_; +}; +} // namespace OHOS::DistributedRdb +#endif // OHOS_DISTRIBUTED_DATA_DATAMGR_SERVICE_RDB_RDB_GENERAL_STORE_H diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.cpp b/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.cpp index abb4f694..74ddeb5f 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.cpp +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.cpp @@ -27,9 +27,11 @@ #include "metadata/store_meta_data.h" #include "permission/permission_validator.h" #include "rdb_notifier_proxy.h" +#include "store/auto_cache.h" #include "types_export.h" #include "utils/anonymous.h" #include "cloud/schema_meta.h" +#include "rdb_general_store.h" using OHOS::DistributedKv::AccountDelegate; using OHOS::DistributedData::CheckerManager; using OHOS::DistributedData::MetaDataManager; @@ -46,6 +48,9 @@ RdbServiceImpl::Factory::Factory() { FeatureSystem::GetInstance().RegisterCreator("relational_store", []() { return std::make_shared(); }); + AutoCache::GetInstance().RegCreator(RDB_DEVICE_COLLABORATION, [](const StoreMetaData &metaData) -> GeneralStore * { + return new RdbGeneralStore(metaData); + }); } RdbServiceImpl::Factory::~Factory() diff --git a/kv_store/frameworks/common/traits.h b/kv_store/frameworks/common/traits.h new file mode 100644 index 00000000..c9d2c3d0 --- /dev/null +++ b/kv_store/frameworks/common/traits.h @@ -0,0 +1,92 @@ +/* + * 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_DISTRIBUTED_DATA_FRAMEWORKS_COMMON_TRAITS_H +#define OHOS_DISTRIBUTED_DATA_FRAMEWORKS_COMMON_TRAITS_H +#include +#include +namespace OHOS { +namespace Traits { +// same_index_of_v +template +inline constexpr size_t same_index_of_v = std::__detail::__variant::__index_of_v; + +// same_in_v +template +inline constexpr bool same_in_v = (same_index_of_v < sizeof...(Types)); + +// convertible_index_of_v +template +struct convertible_index_of : std::integral_constant { +}; + +template +inline constexpr size_t convertible_index_v = convertible_index_of<_Tp, _Types...>::value; + +template +struct convertible_index_of<_Tp, _First, _Rest...> + : std::integral_constant ? 0 : convertible_index_v<_Tp, _Rest...> + 1> { +}; + +// convertible_in_v +template +inline constexpr bool convertible_in_v = (convertible_index_v < sizeof...(Types)); + +template +struct variant_size_of { + static constexpr size_t value = sizeof...(Types); +}; + +template +struct variant_index_of { + static constexpr size_t value = same_index_of_v; +}; + +template +variant_size_of variant_size_test(const std::variant &); + +template +variant_index_of variant_index_test(const T &, const std::variant &); + +template +inline constexpr size_t variant_size_of_v = decltype(variant_size_test(std::declval()))::value; + +template +inline constexpr size_t variant_index_of_v = decltype(variant_index_test(std::declval(), std::declval()))::value; + +template +std::enable_if_t, const T *> get_if(const std::variant *input) +{ + return std::get_if(input); +} + +template ? convertible_index_v : 0> +constexpr std::enable_if_t && convertible_in_v, + std::add_pointer_t>>> +get_if(const std::variant *input) +{ + return std::get_if(input); +} + +template +std::enable_if_t && !convertible_in_v, const T *> get_if( + const std::variant *input) +{ + (void)input; + return nullptr; +} +} // namespace Traits +} // namespace OHOS +#endif // OHOS_DISTRIBUTED_DATA_FRAMEWORKS_COMMON_TRAITS_H diff --git a/relational_store/frameworks/native/rdb/src/rdb_store_manager.cpp b/relational_store/frameworks/native/rdb/src/rdb_store_manager.cpp index c496a61f..86b51373 100644 --- a/relational_store/frameworks/native/rdb/src/rdb_store_manager.cpp +++ b/relational_store/frameworks/native/rdb/src/rdb_store_manager.cpp @@ -24,7 +24,6 @@ #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) #include "rdb_security_manager.h" #include "security_policy.h" -//#include #endif namespace OHOS { diff --git a/relational_store/interfaces/inner_api/rdb/include/asset_value.h b/relational_store/interfaces/inner_api/rdb/include/asset_value.h index ef01f45f..41fa8841 100644 --- a/relational_store/interfaces/inner_api/rdb/include/asset_value.h +++ b/relational_store/interfaces/inner_api/rdb/include/asset_value.h @@ -20,9 +20,11 @@ namespace OHOS::NativeRdb { struct AssetValue { uint32_t version = 0; std::string name; + std::string uri; + std::string createTime; std::string modifyTime; std::string size; - std::string uri; + std::string hash; }; } #endif // OHOS_RELATIONAL_STORE_INNER_API_ASSET_VALUE_H diff --git a/relational_store/interfaces/inner_api/rdb/include/value_object.h b/relational_store/interfaces/inner_api/rdb/include/value_object.h index cbd10dfc..95b2b74f 100644 --- a/relational_store/interfaces/inner_api/rdb/include/value_object.h +++ b/relational_store/interfaces/inner_api/rdb/include/value_object.h @@ -17,36 +17,14 @@ #define NATIVE_RDB_VALUE_OBJECT_H #include -#include #include #include #include "asset_value.h" #include "rdb_visibility.h" +#include "traits.h" namespace OHOS { namespace NativeRdb { -/** - * @brief Indicates the ValueObject {@link ValueObject} type. - */ -enum class ValueObjectType { - /** Indicates the ValueObject type is NULL.*/ - TYPE_NULL = 0, - /** Indicates the ValueObject type is int.*/ - TYPE_INT, - /** Indicates the ValueObject type is double.*/ - TYPE_DOUBLE, - /** Indicates the ValueObject type is string.*/ - TYPE_STRING, - /** Indicates the ValueObject type is bool.*/ - TYPE_BOOL, - /** Indicates the ValueObject type is blob.*/ - TYPE_BLOB, - /** Indicates the ValueObject type is asset.*/ - TYPE_ASSET, - /** Indicates the ValueObject type is assets.*/ - TYPE_ASSETS, -}; - /** * The ValueObject class of RDB. */ @@ -60,6 +38,34 @@ public: using Asset = AssetValue; using Assets = std::vector; using Type = std::variant; + template + inline constexpr static size_t TYPE_INDEX = Traits::variant_index_of_v; + + inline constexpr static size_t TYPE_MAX = Traits::variant_size_of_v; + /** + * @brief Indicates the ValueObject {@link ValueObject} type. + * */ + enum class TypeId + { + /** Indicates the ValueObject type is NULL.*/ + TYPE_NULL = TYPE_INDEX, + /** Indicates the ValueObject type is int.*/ + TYPE_INT = TYPE_INDEX, + /** Indicates the ValueObject type is double.*/ + TYPE_DOUBLE = TYPE_INDEX, + /** Indicates the ValueObject type is string.*/ + TYPE_STRING = TYPE_INDEX, + /** Indicates the ValueObject type is bool.*/ + TYPE_BOOL = TYPE_INDEX, + /** Indicates the ValueObject type is blob.*/ + TYPE_BLOB = TYPE_INDEX, + /** Indicates the ValueObject type is asset.*/ + TYPE_ASSET = TYPE_INDEX, + /** Indicates the ValueObject type is assets.*/ + TYPE_ASSETS = TYPE_INDEX, + TYPE_BUTT + }; + Type value; /** @@ -168,7 +174,7 @@ public: /** * @brief Obtains the type in this {@code ValueObject} object. */ - RDB_API_EXPORT ValueObjectType GetType() const; + RDB_API_EXPORT TypeId GetType() const; /** * @brief Obtains the int value in this {@code ValueObject} object. @@ -212,7 +218,7 @@ public: * * @return Returns the int type ValueObject. */ - operator int () const + operator int() const { return static_cast(std::get(value)); } @@ -222,7 +228,7 @@ public: * * @return Returns the int64_t type ValueObject. */ - operator int64_t () const + operator int64_t() const { return std::get(value); } @@ -232,7 +238,7 @@ public: * * @return Returns the double type ValueObject. */ - operator double () const + operator double() const { return std::get(value); } @@ -242,7 +248,7 @@ public: * * @return Returns the bool type ValueObject. */ - operator bool () const + operator bool() const { return std::get(value); } @@ -252,7 +258,7 @@ public: * * @return Returns the string type ValueObject. */ - operator std::string () const + operator std::string() const { return std::get(value); } @@ -262,7 +268,7 @@ public: * * @return Returns the vector type ValueObject. */ - operator Blob () const + operator Blob() const { return std::get(value); } @@ -272,7 +278,7 @@ public: * * @return Returns the vector type ValueObject. */ - operator Asset () const + operator Asset() const { return std::get(value); } @@ -281,7 +287,7 @@ public: * * @return Returns the vector type ValueObject. */ - operator Assets () const + operator Assets() const { return std::get(value); } @@ -299,23 +305,6 @@ private: template int Get(T &output) const; - template - inline static constexpr size_t index_of_v = std::__detail::__variant::__index_of_v<_Tp, _Types...>; - - template - static std::enable_if_t<(index_of_v<_T, _Rest...> < sizeof...(_Rest)), const _T *> GetIf( - const std::variant<_Rest...> &input) - { - return std::get_if<_T>(&input); - } - - template - static std::enable_if_t<(index_of_v<_T, _Rest...> >= sizeof...(_Rest)), const _T *> GetIf( - const std::variant<_Rest...> &input) - { - return nullptr; - } - template static bool Get(const _T &input, _O &output) { @@ -323,7 +312,15 @@ private: } template - static bool Get(const _T &input, _O &output); + static bool Get(const _T &input, _O &output) + { + const auto *val = Traits::get_if<_First>(&input); + if (val != nullptr) { + output = *val; + return true; + } + return Get<_T, _O, _Rest...>(input, output); + } }; template @@ -331,17 +328,7 @@ bool ValueObject::Convert(const _T &input, std::variant<_Rest...> &output) { return Get<_T, decltype(output), _Rest...>(input, output); } - -template -bool ValueObject::Get(const _T &input, _O &output) -{ - const _First *val = GetIf<_First>(input); - if (val != nullptr) { - output = *val; - return true; - } - return Get<_T, _O, _Rest...>(input, output); -} +using ValueObjectType = ValueObject::TypeId; } // namespace NativeRdb } // namespace OHOS #endif diff --git a/relational_store/test/native/rdb/unittest/rdb_value_bucket_test.cpp b/relational_store/test/native/rdb/unittest/rdb_value_bucket_test.cpp index 039c070c..3c69815d 100644 --- a/relational_store/test/native/rdb/unittest/rdb_value_bucket_test.cpp +++ b/relational_store/test/native/rdb/unittest/rdb_value_bucket_test.cpp @@ -303,7 +303,7 @@ HWTEST_F(ValuesBucketTest, Convert_To_Subset, TestSize.Level1) auto *blob = std::get_if>(&output); EXPECT_TRUE(blob != nullptr); EXPECT_TRUE(*blob == std::vector(10, 'm')); - AssetValue value{.version = 0, .name = "123", .modifyTime = "12", .uri = "my test path" }; + AssetValue value{.version = 0, .name = "123", .uri = "my test path", .createTime = "12", .modifyTime = "12"}; input = value ; output = {}; ValueObject::Convert(input, output); -- Gitee From fa4ed5155f0c595e395bc79c1f71d33cdddeff89 Mon Sep 17 00:00:00 2001 From: Sven Wang Date: Fri, 21 Apr 2023 19:50:31 +0800 Subject: [PATCH 24/44] update Signed-off-by: Sven Wang --- .../frameworks/native/rdb/include/rdb_service_proxy.h | 2 +- relational_store/frameworks/native/rdb/src/rdb_manager_impl.cpp | 2 +- .../frameworks/native/rdb/src/rdb_service_proxy.cpp | 2 +- relational_store/interfaces/inner_api/rdb/include/rdb_service.h | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/relational_store/frameworks/native/rdb/include/rdb_service_proxy.h b/relational_store/frameworks/native/rdb/include/rdb_service_proxy.h index 43099c5a..5ad9d312 100644 --- a/relational_store/frameworks/native/rdb/include/rdb_service_proxy.h +++ b/relational_store/frameworks/native/rdb/include/rdb_service_proxy.h @@ -34,7 +34,7 @@ public: std::string ObtainDistributedTableName(const std::string& device, const std::string& table) override; int32_t InitNotifier(const std::string& bundleName); - int32_t InitNotifier(const std::string& bundleName, const sptr notifier) override; + int32_t InitNotifier(const std::string& bundleName, const sptr ¬ifier) override; int32_t SetDistributedTables(const RdbSyncerParam& param, const std::vector& tables) override; diff --git a/relational_store/frameworks/native/rdb/src/rdb_manager_impl.cpp b/relational_store/frameworks/native/rdb/src/rdb_manager_impl.cpp index 3fc093dd..0f72d35b 100644 --- a/relational_store/frameworks/native/rdb/src/rdb_manager_impl.cpp +++ b/relational_store/frameworks/native/rdb/src/rdb_manager_impl.cpp @@ -101,7 +101,7 @@ int RdbManagerImpl::GetRdbService(const std::string& bundleName, const std::stri return E_NOT_SUPPORTED; } sptr serviceProxy = iface_cast(remote); - if (serviceProxy->InitNotifier(bundleName, storeName) != RDB_OK) { + if (serviceProxy->InitNotifier(bundleName) != RDB_OK) { ZLOGE("init notifier failed"); return E_ERROR; } diff --git a/relational_store/frameworks/native/rdb/src/rdb_service_proxy.cpp b/relational_store/frameworks/native/rdb/src/rdb_service_proxy.cpp index 04388259..8d8f24f5 100644 --- a/relational_store/frameworks/native/rdb/src/rdb_service_proxy.cpp +++ b/relational_store/frameworks/native/rdb/src/rdb_service_proxy.cpp @@ -104,7 +104,7 @@ int32_t RdbServiceProxy::InitNotifier(const std::string &bundleName) return RDB_OK; } -int32_t RdbServiceProxy::InitNotifier(const std::string& bundleName, const sptr notifier) +int32_t RdbServiceProxy::InitNotifier(const std::string& bundleName, const sptr ¬ifier) { MessageParcel reply; int32_t status = IPC_SEND(RDB_SERVICE_CMD_INIT_NOTIFIER, reply, bundleName, notifier); diff --git a/relational_store/interfaces/inner_api/rdb/include/rdb_service.h b/relational_store/interfaces/inner_api/rdb/include/rdb_service.h index 9e1699be..acb86552 100644 --- a/relational_store/interfaces/inner_api/rdb/include/rdb_service.h +++ b/relational_store/interfaces/inner_api/rdb/include/rdb_service.h @@ -60,7 +60,7 @@ public: virtual int32_t DestroyRDBTable(const RdbSyncerParam ¶m) = 0; - virtual int32_t InitNotifier(const std::string& bundleName, const sptr notifier) = 0; + virtual int32_t InitNotifier(const std::string& bundleName, const sptr ¬ifier) = 0; /*Cloud Data*/ virtual int32_t OpenStore(const CloudParam &cloudParam) = 0; -- Gitee From 83aec3632135bb0064b66e9bd5950782225d93a2 Mon Sep 17 00:00:00 2001 From: Sven Wang Date: Fri, 21 Apr 2023 20:04:02 +0800 Subject: [PATCH 25/44] update Signed-off-by: Sven Wang --- .../distributeddataservice/service/rdb/rdb_service_impl.cpp | 2 +- .../distributeddataservice/service/rdb/rdb_service_impl.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.cpp b/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.cpp index 74ddeb5f..2dbe123b 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.cpp +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.cpp @@ -176,7 +176,7 @@ std::string RdbServiceImpl::ObtainDistributedTableName(const std::string &device return DistributedDB::RelationalStoreManager::GetDistributedTableName(uuid, table); } -int32_t RdbServiceImpl::InitNotifier(const std::string &bundleName, const sptr notifier) +int32_t RdbServiceImpl::InitNotifier(const std::string &bundleName, const sptr ¬ifier) { if (!CheckAccess(bundleName, "")) { ZLOGE("permission error"); diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.h b/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.h index 17e12968..7bcde4c0 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.h +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.h @@ -41,7 +41,7 @@ public: /* IPC interface */ std::string ObtainDistributedTableName(const std::string& device, const std::string& table) override; - int32_t InitNotifier(const std::string& bundleName, const sptr notifier) override; + int32_t InitNotifier(const std::string& bundleName, const sptr ¬ifier) override; int32_t SetDistributedTables(const RdbSyncerParam& param, const std::vector& tables) override; -- Gitee From c318ff1d7b2c17c9e9068a96eb54d74484e1fedf Mon Sep 17 00:00:00 2001 From: Sven Wang Date: Sun, 23 Apr 2023 14:04:18 +0800 Subject: [PATCH 26/44] update Signed-off-by: Sven Wang --- .../service/rdb/rdb_general_store.cpp | 99 ++++++++++--------- .../service/rdb/rdb_general_store.h | 3 + kv_store/frameworks/common/traits.h | 21 ++++ 3 files changed, 77 insertions(+), 46 deletions(-) diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_general_store.cpp b/datamgr_service/services/distributeddataservice/service/rdb/rdb_general_store.cpp index 8d5faf4b..cbfa6624 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_general_store.cpp +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_general_store.cpp @@ -82,21 +82,25 @@ int32_t RdbGeneralStore::Execute(const std::string &table, const std::string &sq int32_t RdbGeneralStore::Insert(const std::string &table, VBucket &&values) { - ValuesBucket rdbVBucket; - for (auto &[key, value] : values) { - rdbVBucket.Put(key, Convert(std::move(value))); + int64_t outRowId; + auto ret = store_->Insert(outRowId, table, Convert(std::move(values))); + return (ret == NativeRdb::E_OK) ? GeneralError::E_OK : GeneralError::E_ERROR; +} + +int32_t RdbGeneralStore::BatchInsert(const std::string &table, VBuckets &&values) +{ + std::vector rdbVBucket; + for (auto &bucket : values) { + rdbVBucket.push_back(Convert(std::move(bucket))); } int64_t outRowId; - auto ret = store_->Insert(outRowId, table, std::move(rdbVBucket)); + auto ret = store_->BatchInsert(outRowId, table, std::move(rdbVBucket)); if (ret == NativeRdb::E_OK) { return GeneralError::E_OK; } return GeneralError::E_ERROR; } -int32_t RdbGeneralStore::BatchInsert(const std::string &table, VBuckets &&values) -{ - return 0; -} + int32_t RdbGeneralStore::Update(const std::string &table, const std::string &sql, VBucket &&values) { return 0; @@ -130,6 +134,15 @@ int32_t RdbGeneralStore::Sync(const Devices &devices, int32_t mode, const GenQue return 0; } +NativeRdb::ValuesBucket RdbGeneralStore::Convert(VBucket &&bucket) +{ + ValuesBucket rdbVBucket; + for (auto &[key, value] : bucket) { + rdbVBucket.Put(key, Convert(std::move(value))); + } + return rdbVBucket; +} + NativeRdb::ValueObject RdbGeneralStore::Convert(Value &&value) { ValueObject rdbValue; @@ -137,19 +150,11 @@ NativeRdb::ValueObject RdbGeneralStore::Convert(Value &&value) return rdbValue; } if (value.index() == TYPE_INDEX) { - auto *asset = Traits::get_if(&value); + Asset *asset = Traits::get_if(&value); if (asset == nullptr) { return NativeRdb::ValueObject(); } - AssetValue assetValue; - assetValue.version = asset->version; - assetValue.name = asset->name; - assetValue.uri = asset->uri; - assetValue.createTime = asset->createTime; - assetValue.modifyTime = asset->modifyTime; - assetValue.size = asset->size; - assetValue.hash = asset->hash; - return std::move(assetValue); + return ConvertAsset(std::move(*asset)); } if (value.index() == TYPE_INDEX) { @@ -159,20 +164,13 @@ NativeRdb::ValueObject RdbGeneralStore::Convert(Value &&value) } std::vector assetsValue; for (auto &asset : *assets) { - AssetValue assetValue; - assetValue.version = asset.version; - assetValue.name = asset.name; - assetValue.uri = asset.uri; - assetValue.createTime = asset.createTime; - assetValue.modifyTime = asset.modifyTime; - assetValue.size = asset.size; - assetValue.hash = asset.hash; - assetsValue.push_back(std::move(assetValue)); + assetsValue.push_back(ConvertAsset(std::move(asset))); } return std::move(assetsValue); } return NativeRdb::ValueObject(); } + DistributedData::Value RdbGeneralStore::Convert(ValueObject &&rdbValue) { DistributedData::Value value; @@ -184,16 +182,7 @@ DistributedData::Value RdbGeneralStore::Convert(ValueObject &&rdbValue) if (rdbAsset == nullptr) { return {}; } - value = Asset{ - .version = rdbAsset->version, - .name = rdbAsset->name, - .uri = rdbAsset->uri, - .createTime = rdbAsset->createTime, - .modifyTime = rdbAsset->modifyTime, - .size = rdbAsset->size, - .hash = rdbAsset->hash - }; - return value; + return ConvertAsset(std::move(*rdbAsset)); } if (rdbValue.value.index() == Traits::variant_index_of_v) { @@ -203,18 +192,36 @@ DistributedData::Value RdbGeneralStore::Convert(ValueObject &&rdbValue) } Assets assets; for (auto &rdbAsset : *rdbAssets) { - assets.push_back(Asset{ - .version = rdbAsset.version, - .name = rdbAsset.name, - .uri = rdbAsset.uri, - .createTime = rdbAsset.createTime, - .modifyTime = rdbAsset.modifyTime, - .size = rdbAsset.size, - .hash = rdbAsset.hash - }); + assets.push_back(ConvertAsset(std::move(rdbAsset))); } return std::move(assets); } return value; } + +NativeRdb::AssetValue RdbGeneralStore::ConvertAsset(Asset &&value) +{ + return NativeRdb::AssetValue{ + .version = std::move(value.version), + .name = std::move(value.name), + .uri = std::move(value.uri), + .createTime = std::move(value.createTime), + .modifyTime = std::move(value.modifyTime), + .size = std::move(value.size), + .hash = std::move(value.hash) + }; +} + +DistributedData::Asset RdbGeneralStore::ConvertAsset(AssetValue &&value) +{ + return DistributedData::Asset { + .version = std::move(value.version), + .name = std::move(value.name), + .uri = std::move(value.uri), + .createTime = std::move(value.createTime), + .modifyTime = std::move(value.modifyTime), + .size = std::move(value.size), + .hash = std::move(value.hash) + }; +} } // namespace OHOS::DistributedRdb diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_general_store.h b/datamgr_service/services/distributeddataservice/service/rdb/rdb_general_store.h index bfd63652..128774b7 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_general_store.h +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_general_store.h @@ -49,8 +49,11 @@ public: int32_t Sync(const Devices &devices, int32_t mode, const GenQuery &query, Async async, bool wait) override; private: + NativeRdb::ValuesBucket Convert(DistributedData::VBucket &&bucket); NativeRdb::ValueObject Convert(DistributedData::Value &&value); DistributedData::Value Convert(NativeRdb::ValueObject &&rdbValue); + NativeRdb::AssetValue ConvertAsset(DistributedData::Asset &&value); + DistributedData::Asset ConvertAsset(NativeRdb::AssetValue &&value); RdbManager manager_; RdbDelegate *delegate_ = nullptr; diff --git a/kv_store/frameworks/common/traits.h b/kv_store/frameworks/common/traits.h index c9d2c3d0..08eeb1a4 100644 --- a/kv_store/frameworks/common/traits.h +++ b/kv_store/frameworks/common/traits.h @@ -66,12 +66,26 @@ inline constexpr size_t variant_size_of_v = decltype(variant_size_test(std::decl template inline constexpr size_t variant_index_of_v = decltype(variant_index_test(std::declval(), std::declval()))::value; +template +std::enable_if_t, T *> get_if(std::variant *input) +{ + return std::get_if(input); +} + template std::enable_if_t, const T *> get_if(const std::variant *input) { return std::get_if(input); } +template ? convertible_index_v : 0> +constexpr std::enable_if_t && convertible_in_v, + std::add_pointer_t>>> +get_if(std::variant *input) +{ + return std::get_if(input); +} + template ? convertible_index_v : 0> constexpr std::enable_if_t && convertible_in_v, std::add_pointer_t>>> @@ -80,6 +94,13 @@ get_if(const std::variant *input) return std::get_if(input); } +template +std::enable_if_t && !convertible_in_v, T *> get_if(std::variant *input) +{ + (void)input; + return nullptr; +} + template std::enable_if_t && !convertible_in_v, const T *> get_if( const std::variant *input) -- Gitee From 67f7f9ebf8868dcf13d98a133123a0f0ed8d8e83 Mon Sep 17 00:00:00 2001 From: Sven Wang Date: Sun, 23 Apr 2023 17:42:37 +0800 Subject: [PATCH 27/44] update Signed-off-by: Sven Wang --- .../interfaces/inner_api/js/@ohos.base.d.ts | 81 + .../inner_api/js/@ohos.data.ValuesBucket.d.ts | 52 + .../inner_api/js/@ohos.data.rdb.d.ts | 934 +++++++++ .../js/@ohos.data.relationalStore.d.ts | 1860 +++++++++++++++++ .../inner_api/js/data/rdb/resultSet.d.ts | 303 +++ 5 files changed, 3230 insertions(+) create mode 100644 relational_store/interfaces/inner_api/js/@ohos.base.d.ts create mode 100644 relational_store/interfaces/inner_api/js/@ohos.data.ValuesBucket.d.ts create mode 100644 relational_store/interfaces/inner_api/js/@ohos.data.rdb.d.ts create mode 100644 relational_store/interfaces/inner_api/js/@ohos.data.relationalStore.d.ts create mode 100644 relational_store/interfaces/inner_api/js/data/rdb/resultSet.d.ts diff --git a/relational_store/interfaces/inner_api/js/@ohos.base.d.ts b/relational_store/interfaces/inner_api/js/@ohos.base.d.ts new file mode 100644 index 00000000..dbcb9af2 --- /dev/null +++ b/relational_store/interfaces/inner_api/js/@ohos.base.d.ts @@ -0,0 +1,81 @@ +/* + * 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. + */ + +/** + * Defines the basic callback. + * @syscap SystemCapability.Base + * @typedef Callback + * @since 6 + */ +export interface Callback { + /** + * Defines the callback info. + * @param { T } data + * @since 6 + */ + (data: T): void; +} + +/** + * Defines the basic error callback. + * @syscap SystemCapability.Base + * @typedef ErrorCallback + * @since 6 + */ +export interface ErrorCallback { + /** + * Defines the basic error callback. + * @param { T } err + * @since 6 + */ + (err: T): void; +} + +/** + * Defines the basic async callback. + * @syscap SystemCapability.Base + * @typedef AsyncCallback + * @since 6 + */ +export interface AsyncCallback { + /** + * Defines the callback data. + * @param { BusinessError } err + * @param { T } data + * @since 6 + */ + (err: BusinessError, data: T): void; +} + +/** + * Defines the error interface. + * @syscap SystemCapability.Base + * @typedef BusinessError + * @since 6 + */ +export interface BusinessError extends Error { + /** + * Defines the basic error code. + * @type { number } code + * @since 6 + */ + code: number; + /** + * Defines the additional information for business + * @type { ?T } data + * @since 9 + */ + data?: T; +} diff --git a/relational_store/interfaces/inner_api/js/@ohos.data.ValuesBucket.d.ts b/relational_store/interfaces/inner_api/js/@ohos.data.ValuesBucket.d.ts new file mode 100644 index 00000000..47ea9819 --- /dev/null +++ b/relational_store/interfaces/inner_api/js/@ohos.data.ValuesBucket.d.ts @@ -0,0 +1,52 @@ +/* + * 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. + */ + +/** + * Indicates possible value types + * + * @syscap SystemCapability.DistributedDataManager.DataShare.Core + * @systemapi + * @StageModelOnly + * @since 9 + */ +export class Asset { + name: string; + uri: string; + createTime: string; + modifyTime: string; + size: string; +} + +/** + * Indicates possible value types + * + * @syscap SystemCapability.DistributedDataManager.DataShare.Core + * @systemapi + * @StageModelOnly + * @since 9 + */ +export type ValueType = number | string | boolean; + +/** + * Values in buckets are stored in key-value pairs + * + * @syscap SystemCapability.DistributedDataManager.DataShare.Core + * @systemapi + * @StageModelOnly + * @since 9 + */ +export type ValuesBucket = { + [key: string]: ValueType | Uint8Array | Asset | Asset null; +}; diff --git a/relational_store/interfaces/inner_api/js/@ohos.data.rdb.d.ts b/relational_store/interfaces/inner_api/js/@ohos.data.rdb.d.ts new file mode 100644 index 00000000..0aaf6678 --- /dev/null +++ b/relational_store/interfaces/inner_api/js/@ohos.data.rdb.d.ts @@ -0,0 +1,934 @@ +/* + * 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. + */ + +import { AsyncCallback, Callback } from './@ohos.base'; +import { ResultSet as _ResultSet } from './data/rdb/resultSet'; +import Context from './application/BaseContext'; + +/** + * Provides methods for rdbStore create and delete. + * + * @namespace rdb + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 7 + * @deprecated since 9 + * @useinstead ohos.data.relationalStore + */ +declare namespace rdb { + /** + * Obtains an RDB store. + * You can set parameters of the RDB store as required. In general, this method is recommended + * to obtain a rdb store. + * + * @param { Context } context - Indicates the context of application or capability. + * @param { StoreConfig } config - Indicates the {@link StoreConfig} configuration of the database related to this RDB store. + * @param { number } version - Indicates the database version for upgrade or downgrade. + * @param { AsyncCallback } callback - the RDB store {@link RdbStore}. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 7 + * @deprecated since 9 + * @useinstead ohos.data.relationalStore.getRdbStore + */ + function getRdbStore(context: Context, config: StoreConfig, version: number, callback: AsyncCallback): void; + + /** + * Obtains an RDB store. + * You can set parameters of the RDB store as required. In general, this method is recommended + * to obtain a rdb store. + * + * @param { Context } context - Indicates the context of application or capability. + * @param { StoreConfig } config - Indicates the {@link StoreConfig} configuration of the database related to this RDB store. + * @param { number } version - Indicates the database version for upgrade or downgrade. + * @returns { Promise } the RDB store {@link RdbStore}. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 7 + * @deprecated since 9 + * @useinstead ohos.data.relationalStore.getRdbStore + */ + function getRdbStore(context: Context, config: StoreConfig, version: number): Promise; + + /** + * Deletes the database with a specified name. + * + * @param { Context } context - Indicates the context of application or capability. + * @param { string } name - Indicates the database name. + * @param { AsyncCallback } callback - the callback of deleteRdbStore. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 7 + * @deprecated since 9 + * @useinstead ohos.data.relationalStore.deleteRdbStore + */ + function deleteRdbStore(context: Context, name: string, callback: AsyncCallback): void; + /** + * Deletes the database with a specified name. + * + * @param { Context } context - Indicates the context of application or capability. + * @param { string } name - Indicates the database name. + * @returns { Promise } the promise returned by the function. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 7 + * @deprecated since 9 + * @useinstead ohos.data.relationalStore.deleteRdbStore + */ + function deleteRdbStore(context: Context, name: string): Promise; + + /** + * Indicates the database synchronization mode. + * + * @enum { number } + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 8 + * @deprecated since 9 + * @useinstead ohos.data.relationalStore.SyncMode + */ + enum SyncMode { + /** + * Indicates the data is pushed to remote device from local device. + * + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 8 + * @deprecated since 9 + * @useinstead ohos.data.relationalStore.SyncMode.SYNC_MODE_PUSH + */ + SYNC_MODE_PUSH = 0, + + /** + * Indicates the data is pulled from remote device to local device. + * + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 8 + * @deprecated since 9 + * @useinstead ohos.data.relationalStore.SyncMode.SYNC_MODE_PULL + */ + SYNC_MODE_PULL = 1 + } + + /** + * Describes the subscription type. + * + * @permission ohos.permission.DISTRIBUTED_DATASYNC + * @enum { number } + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 8 + * @deprecated since 9 + * @useinstead ohos.data.relationalStore.SubscribeType + */ + enum SubscribeType { + /** + * Subscription to remote data changes + * + * @permission ohos.permission.DISTRIBUTED_DATASYNC + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 8 + * @deprecated since 9 + * @useinstead ohos.data.relationalStore.SubscribeType.SUBSCRIBE_TYPE_REMOTE + */ + SUBSCRIBE_TYPE_REMOTE = 0 + } + + /** + * Provides methods for managing the relational database (RDB). + * This class provides methods for creating, querying, updating, and deleting RDBs. + * + * @interface RdbStore + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 7 + * @deprecated since 9 + * @useinstead ohos.data.relationalStore.RdbStore + */ + interface RdbStore { + /** + * Inserts a row of data into the target table. + * + * @param { string } table - Indicates the row of data to be inserted into the table. + * @param { ValuesBucket } values - Indicates the row of data {@link ValuesBucket} to be inserted into the table. + * @param { AsyncCallback } callback - the row ID if the operation is successful. returns -1 otherwise. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 7 + * @deprecated since 9 + * @useinstead ohos.data.relationalStore.RdbStore.insert + */ + insert(table: string, values: ValuesBucket, callback: AsyncCallback): void; + + /** + * Inserts a row of data into the target table. + * + * @param { string } table - Indicates the row of data to be inserted into the table. + * @param { ValuesBucket } values - Indicates the row of data {@link ValuesBucket} to be inserted into the table. + * @returns { Promise } return the row ID if the operation is successful. return -1 otherwise. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 7 + * @deprecated since 9 + * @useinstead ohos.data.relationalStore.RdbStore.insert + */ + insert(table: string, values: ValuesBucket): Promise; + + /** + * Inserts a batch of data into the target table. + * + * @param { string } table - Indicates the target table. + * @param { Array } values - Indicates the rows of data {@link ValuesBucket} to be inserted into the table. + * @param { AsyncCallback } callback - the number of values that were inserted if the operation is successful. returns -1 otherwise. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 7 + * @deprecated since 9 + * @useinstead ohos.data.relationalStore.RdbStore.batchInsert + */ + batchInsert(table: string, values: Array, callback: AsyncCallback): void; + + /** + * Inserts a batch of data into the target table. + * + * @param { string } table - Indicates the target table. + * @param { Array } values - Indicates the rows of data {@link ValuesBucket} to be inserted into the table. + * @returns { Promise } return the number of values that were inserted if the operation is successful. returns -1 otherwise. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 7 + * @deprecated since 9 + * @useinstead ohos.data.relationalStore.RdbStore.batchInsert + */ + batchInsert(table: string, values: Array): Promise; + + /** + * Updates data in the database based on a a specified instance object of RdbPredicates. + * + * @param { ValuesBucket } values - Indicates 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 { RdbPredicates } predicates - Indicates the specified update condition by the instance object of {@link RdbPredicates}. + * @param { AsyncCallback } callback - the number of affected rows. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 7 + * @deprecated since 9 + * @useinstead ohos.data.relationalStore.RdbStore.update + */ + update(values: ValuesBucket, predicates: RdbPredicates, callback: AsyncCallback): void; + + /** + * Updates data in the database based on a a specified instance object of RdbPredicates. + * + * @param { ValuesBucket } values - Indicates 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 { RdbPredicates } predicates - Indicates the specified update condition by the instance object of {@link RdbPredicates}. + * @returns { Promise } return the number of affected rows. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 7 + * @deprecated since 9 + * @useinstead ohos.data.relationalStore.RdbStore.update + */ + update(values: ValuesBucket, predicates: RdbPredicates): Promise; + + /** + * Deletes data from the database based on a specified instance object of RdbPredicates. + * + * @param { RdbPredicates } predicates - the specified delete condition by the instance object of {@link RdbPredicates}. + * @param { AsyncCallback } callback - the number of affected rows. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 7 + * @deprecated since 9 + * @useinstead ohos.data.relationalStore.RdbStore.delete + */ + delete(predicates: RdbPredicates, callback: AsyncCallback): void; + + /** + * Deletes data from the database based on a specified instance object of RdbPredicates. + * + * @param { RdbPredicates } predicates - the specified delete condition by the instance object of {@link RdbPredicates}. + * @returns { Promise } return the number of affected rows. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 7 + * @deprecated since 9 + * @useinstead ohos.data.relationalStore.RdbStore.delete + */ + delete(predicates: RdbPredicates): Promise; + + /** + * Queries data in the database based on specified conditions. + * + * @param { RdbPredicates } predicates - the specified query condition by the instance object of {@link RdbPredicates}. + * @param { Array } columns - the columns to query. If the value is empty array, the query applies to all columns. + * @param { AsyncCallback } callback - the {@link ResultSet} object if the operation is successful. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 7 + * @deprecated since 9 + * @useinstead ohos.data.relationalStore.RdbStore.query + */ + query(predicates: RdbPredicates, columns: Array, callback: AsyncCallback): void; + + /** + * Queries data in the database based on specified conditions. + * + * @param { RdbPredicates } predicates - the specified query condition by the instance object of {@link RdbPredicates}. + * @param { Array } columns - the columns to query. If the value is null, the query applies to all columns. + * @returns { Promise } return the {@link ResultSet} object if the operation is successful. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 7 + * @deprecated since 9 + * @useinstead ohos.data.relationalStore.RdbStore.query + */ + query(predicates: RdbPredicates, columns?: Array): Promise; + + /** + * Queries data in the database based on SQL statement. + * + * @param { string } sql - Indicates the SQL statement to execute. + * @param { Array } bindArgs - Indicates the {@link ValueType} values of the parameters in the SQL statement. The values are strings. + * @param { AsyncCallback } callback + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 8 + * @deprecated since 9 + * @useinstead ohos.data.relationalStore.RdbStore.querySql + */ + querySql(sql: string, bindArgs: Array, callback: AsyncCallback): void; + + /** + * Queries data in the database based on SQL statement. + * + * @param { string } sql - Indicates the SQL statement to execute. + * @param { Array } bindArgs - Indicates the {@link ValueType} values of the parameters in the SQL statement. The values are strings. + * @returns { Promise } return the {@link ResultSet} object if the operation is successful. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 8 + * @deprecated since 9 + * @useinstead ohos.data.relationalStore.RdbStore.querySql + */ + querySql(sql: string, bindArgs?: Array): Promise; + + /** + * Executes an SQL statement that contains specified parameters but returns no value. + * + * @param { string } sql - Indicates the SQL statement to execute. + * @param { Array } bindArgs - Indicates the {@link ValueType} values of the parameters in the SQL statement. The values are strings. + * @param { AsyncCallback } callback - the callback of executeSql. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 8 + * @deprecated since 9 + * @useinstead ohos.data.relationalStore.RdbStore.executeSql + */ + executeSql(sql: string, bindArgs: Array, callback: AsyncCallback): void; + + /** + * Executes an SQL statement that contains specified parameters but returns no value. + * + * @param { string } sql - Indicates the SQL statement to execute. + * @param { Array } bindArgs - Indicates the {@link ValueType} values of the parameters in the SQL statement. The values are strings. + * @returns { Promise } the promise returned by the function. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 8 + * @deprecated since 9 + * @useinstead ohos.data.relationalStore.RdbStore.executeSql + */ + executeSql(sql: string, bindArgs?: Array): Promise; + + /** + * Begin Transaction before execute your sql. + * + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 8 + * @deprecated since 9 + * @useinstead ohos.data.relationalStore.RdbStore.beginTransaction + */ + beginTransaction(): void; + + /** + * Commit the the sql you have executed. + * + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 8 + * @deprecated since 9 + * @useinstead ohos.data.relationalStore.RdbStore.commit + */ + commit(): void; + + /** + * Roll back the sql you have already executed. + * + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 8 + * @deprecated since 9 + * @useinstead ohos.data.relationalStore.RdbStore.rollBack + */ + rollBack(): void; + + /** + * Set table to be distributed table. + * + * @permission ohos.permission.DISTRIBUTED_DATASYNC + * @param { Array } tables - Indicates the tables name you want to set. + * @param { AsyncCallback } callback - the callback of setDistributedTables. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 8 + * @deprecated since 9 + * @useinstead ohos.data.relationalStore.RdbStore.setDistributedTables + */ + setDistributedTables(tables: Array, callback: AsyncCallback): void; + + /** + * Set table to be distributed table. + * + * @permission ohos.permission.DISTRIBUTED_DATASYNC + * @param { Array } tables - Indicates the tables name you want to set. + * @returns { Promise } the promise returned by the function. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 8 + * @deprecated since 9 + * @useinstead ohos.data.relationalStore.RdbStore.setDistributedTables + */ + setDistributedTables(tables: Array): Promise; + + /** + * Obtain distributed table name of specified remote device according to local table name. + * When query remote device database, distributed table name is needed. + * + * @permission ohos.permission.DISTRIBUTED_DATASYNC + * @param { string } device - Indicates the remote device. + * @param { string } table - {string}: the distributed table name. + * @param { AsyncCallback } callback + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 8 + * @deprecated since 9 + * @useinstead ohos.data.relationalStore.RdbStore.obtainDistributedTableName + */ + obtainDistributedTableName(device: string, table: string, callback: AsyncCallback): void; + + /** + * Obtain distributed table name of specified remote device according to local table name. + * When query remote device database, distributed table name is needed. + * + * @permission ohos.permission.DISTRIBUTED_DATASYNC + * @param { string } device - Indicates the remote device. + * @param { string } table + * @returns { Promise } {string}: the distributed table name. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 8 + * @deprecated since 9 + * @useinstead ohos.data.relationalStore.RdbStore.obtainDistributedTableName + */ + obtainDistributedTableName(device: string, table: string): Promise; + + /** + * Sync data between devices. + * + * @permission ohos.permission.DISTRIBUTED_DATASYNC + * @param { SyncMode } mode - Indicates the remote device. + * @param { RdbPredicates } predicates - {Array<[string, number]>}: devices sync status array, {string}: device id, {number}: device sync status. + * @param { AsyncCallback> } callback + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 8 + * @deprecated since 9 + * @useinstead ohos.data.relationalStore.RdbStore.sync + */ + sync(mode: SyncMode, predicates: RdbPredicates, callback: AsyncCallback>): void; + + /** + * Sync data between devices. + * + * @permission ohos.permission.DISTRIBUTED_DATASYNC + * @param { SyncMode } mode - Indicates the remote device. + * @param { RdbPredicates } predicates + * @returns { Promise> } {Array<[string, number]>}: devices sync status array, {string}: device id, {number}: device sync status. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 8 + * @deprecated since 9 + * @useinstead ohos.data.relationalStore.RdbStore.sync + */ + sync(mode: SyncMode, predicates: RdbPredicates): Promise>; + + /** + * Registers an observer for the database. When data in the distributed database changes, + * the callback will be invoked. + * + * @param { 'dataChange' } event - Indicates the event must be string 'dataChange'. + * @param { SubscribeType } type - Indicates the subscription type, which is defined in {@link SubscribeType}.If its value is SUBSCRIBE_TYPE_REMOTE, ohos.permission.DISTRIBUTED_DATASYNC is required. + * @param { Callback> } observer - {Array}: the observer of data change events in the distributed database. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 8 + * @deprecated since 9 + * @useinstead ohos.data.relationalStore.RdbStore.on + */ + on(event: 'dataChange', type: SubscribeType, observer: Callback>): void; + + /** + * Remove specified observer of specified type from the database. + * + * @param { 'dataChange' } event - Indicates the event must be string 'dataChange'. + * @param { SubscribeType } type - Indicates the subscription type, which is defined in {@link SubscribeType}.If its value is SUBSCRIBE_TYPE_REMOTE, ohos.permission.DISTRIBUTED_DATASYNC is required. + * @param { Callback> } observer - {Array}: the data change observer already registered. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 8 + * @deprecated since 9 + * @useinstead ohos.data.relationalStore.RdbStore.off + */ + off(event: 'dataChange', type: SubscribeType, observer: Callback>): void; + } + + /** + * Indicates possible value types + * + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 7 + * @deprecated since 9 + * @useinstead ohos.data.relationalStore.ValueType + */ + type ValueType = number | string | boolean; + + /** + * Values in buckets are stored in key-value pairs + * + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 7 + * @deprecated since 9 + * @useinstead ohos.data.relationalStore.ValuesBucket + */ + type ValuesBucket = { [key: string]: ValueType | Uint8Array | null }; + + /** + * Manages relational database configurations. + * + * @interface StoreConfig + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 7 + * @deprecated since 9 + * @useinstead ohos.data.relationalStore.StoreConfig + */ + interface StoreConfig { + name: string; + } + + /** + * Manages relational database configurations. + * + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 7 + * @deprecated since 9 + * @useinstead ohos.data.relationalStore.RdbPredicates + */ + class RdbPredicates { + /** + * A parameterized constructor used to create an RdbPredicates instance. + * + * @param { string } name - Indicates the table name of the database. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 7 + * @deprecated since 9 + * @useinstead ohos.data.relationalStore.RdbPredicates.constructor + */ + constructor(name: string); + + /** + * Sync data between devices. + * When query database, this function should not be called. + * + * @param { Array } devices - Indicates specified remote devices. + * @returns { RdbPredicates } - the {@link RdbPredicates} self. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 8 + * @deprecated since 9 + * @useinstead ohos.data.relationalStore.RdbPredicates.inDevices + */ + inDevices(devices: Array): RdbPredicates; + + /** + * Specify all remote devices which connect to local device when syncing distributed database. + * When query database, this function should not be called. + * + * @returns { RdbPredicates } - the {@link RdbPredicates} self. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 8 + * @deprecated since 9 + * @useinstead ohos.data.relationalStore.RdbPredicates.inAllDevices + */ + inAllDevices(): RdbPredicates; + + /** + * Configure the RdbPredicates to match the field whose data type is ValueType and value is equal + * to a specified value. + * This method is similar to = of the SQL statement. + * + * @param { string } field - Indicates the column name in the database table. + * @param { ValueType } value - Indicates the value to match with the {@link RdbPredicates}. + * @returns { RdbPredicates } - the {@link RdbPredicates} self. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 7 + * @deprecated since 9 + * @useinstead ohos.data.relationalStore.RdbPredicates.equalTo + */ + equalTo(field: string, value: ValueType): RdbPredicates; + + /** + * Configure the RdbPredicates to match the field whose data type is ValueType and value is not equal to + * a specified value. + * This method is similar to != of the SQL statement. + * + * @param { string } field - Indicates the column name in the database table. + * @param { ValueType } value - Indicates the value to match with the {@link RdbPredicates}. + * @returns { RdbPredicates } - the {@link RdbPredicates} self. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 7 + * @deprecated since 9 + * @useinstead ohos.data.relationalStore.RdbPredicates.notEqualTo + */ + notEqualTo(field: string, value: ValueType): RdbPredicates; + + /** + * Adds a left parenthesis to the RdbPredicates. + * This method is similar to ( of the SQL statement and needs to be used together with endWrap(). + * + * @returns { RdbPredicates } - the {@link RdbPredicates} with the left parenthesis. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 7 + * @deprecated since 9 + * @useinstead ohos.data.relationalStore.RdbPredicates.beginWrap + */ + beginWrap(): RdbPredicates; + + /** + * Adds a right parenthesis to the RdbPredicates. + * This method is similar to ) of the SQL statement and needs to be used together + * with beginWrap(). + * + * @returns { RdbPredicates } - the {@link RdbPredicates} with the right parenthesis. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 7 + * @deprecated since 9 + * @useinstead ohos.data.relationalStore.RdbPredicates.endWrap + */ + endWrap(): RdbPredicates; + + /** + * Adds an or condition to the RdbPredicates. + * This method is similar to or of the SQL statement. + * + * @returns { RdbPredicates } Returns the {@link RdbPredicates} with the or condition. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 7 + * @deprecated since 9 + * @useinstead ohos.data.relationalStore.RdbPredicates.or + */ + or(): RdbPredicates; + + /** + * Adds an and condition to the RdbPredicates. + * This method is similar to or of the SQL statement. + * + * @returns { RdbPredicates } Returns the {@link RdbPredicates} with the or condition. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 7 + * @deprecated since 9 + * @useinstead ohos.data.relationalStore.RdbPredicates.and + */ + and(): RdbPredicates; + + /** + * Configure the RdbPredicates to match the field whose data type is string and value + * contains a specified value. + * This method is similar to contains of the SQL statement. + * + * @param { string } field - Indicates the column name in the database table. + * @param { string } value - Indicates the value to match with the {@link RdbPredicates}. + * @returns { RdbPredicates } - the {@link RdbPredicates} self. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 7 + * @deprecated since 9 + * @useinstead ohos.data.relationalStore.RdbPredicates.contains + */ + contains(field: string, value: string): RdbPredicates; + + /** + * Configure the RdbPredicates to match the field whose data type is string and value starts + * with a specified string. + * This method is similar to value% of the SQL statement. + * + * @param { string } field - Indicates the column name in the database table. + * @param { string } value - Indicates the value to match with the {@link RdbPredicates}. + * @returns { RdbPredicates } - the {@link RdbPredicates} self. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 7 + * @deprecated since 9 + * @useinstead ohos.data.relationalStore.RdbPredicates.beginsWith + */ + beginsWith(field: string, value: string): RdbPredicates; + + /** + * Configure the RdbPredicates to match the field whose data type is string and value + * ends with a specified string. + * This method is similar to %value of the SQL statement. + * + * @param { string } field - Indicates the column name in the database table. + * @param { string } value - Indicates the value to match with the {@link RdbPredicates}. + * @returns { RdbPredicates } - the {@link RdbPredicates} self. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 7 + * @deprecated since 9 + * @useinstead ohos.data.relationalStore.RdbPredicates.endsWith + */ + endsWith(field: string, value: string): RdbPredicates; + + /** + * Configure the RdbPredicates to match the fields whose value is null. + * This method is similar to is null of the SQL statement. + * + * @param { string } field - Indicates the column name in the database table. + * @returns { RdbPredicates } - the {@link RdbPredicates} self. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 7 + * @deprecated since 9 + * @useinstead ohos.data.relationalStore.RdbPredicates.isNull + */ + isNull(field: string): RdbPredicates; + + /** + * Configure the RdbPredicates to match the specified fields whose value is not null. + * This method is similar to is not null of the SQL statement. + * + * @param { string } field - Indicates the column name in the database table. + * @returns { RdbPredicates } - the {@link RdbPredicates} self. + * @throws { BusinessError } 401 - if the parameter type is incorrect. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 7 + * @deprecated since 9 + * @useinstead ohos.data.relationalStore.RdbPredicates.isNotNull + */ + isNotNull(field: string): RdbPredicates; + + /** + * Configure the RdbPredicates to match the fields whose data type is string and value is + * similar to a specified string. + * This method is similar to like of the SQL statement. + * + * @param { string } field - Indicates the column name in the database table. + * @param { string } value - Indicates the value to match with the {@link RdbPredicates}. + * @returns { RdbPredicates } - the {@link RdbPredicates} that match the specified field. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 7 + * @deprecated since 9 + * @useinstead ohos.data.relationalStore.RdbPredicates.like + */ + like(field: string, value: string): RdbPredicates; + + /** + * Configure RdbPredicates to match the specified field whose data type is string and the value contains + * a wildcard. + * Different from like, the input parameters of this method are case-sensitive. + * + * @param { string } field - Indicates the column name in the database table. + * @param { string } value - Indicates the value to match with the {@link RdbPredicates}. + * @returns { RdbPredicates } - the SQL statement with the specified {@link RdbPredicates}. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 7 + * @deprecated since 9 + * @useinstead ohos.data.relationalStore.RdbPredicates.glob + */ + glob(field: string, value: string): RdbPredicates; + + /** + * Configure RdbPredicates to match the specified field whose data type is string and the value contains + * a wildcard. + * + * @param { string } field - Indicates the column name. + * @param { ValueType } low - Indicates the minimum value. + * @param { ValueType } high - Indicates the maximum value. + * @returns { RdbPredicates } - the SQL statement with the specified {@link RdbPredicates}. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 7 + * @deprecated since 9 + * @useinstead ohos.data.relationalStore.RdbPredicates.between + */ + between(field: string, low: ValueType, high: ValueType): RdbPredicates; + + /** + * Configure RdbPredicates to match the specified field whose data type is int and value is + * out of a given range. + * + * @param { string } field - Indicates the column name in the database table. + * @param { ValueType } low - Indicates the minimum value. + * @param { ValueType } high - Indicates the maximum value to. + * @returns { RdbPredicates } - the SQL statement with the specified {@link RdbPredicates}. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 7 + * @deprecated since 9 + * @useinstead ohos.data.relationalStore.RdbPredicates.notBetween + */ + notBetween(field: string, low: ValueType, high: ValueType): RdbPredicates; + + /** + * Restricts the value of the field to be greater than the specified value. + * + * @param { string } field - Indicates the column name in the database table. + * @param { ValueType } value - Indicates the value to match with the {@link RdbPredicates}. + * @returns { RdbPredicates } - the SQL query statement with the specified {@link RdbPredicates}. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 7 + * @deprecated since 9 + * @useinstead ohos.data.relationalStore.RdbPredicates.greaterThan + */ + greaterThan(field: string, value: ValueType): RdbPredicates; + + /** + * Restricts the value of the field to be smaller than the specified value. + * + * @param { string } field - Indicates the column name in the database table. + * @param { ValueType } value - Indicates the value to match with the {@link RdbPredicates}. + * @returns { RdbPredicates } - the SQL query statement with the specified {@link RdbPredicates}. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 7 + * @deprecated since 9 + * @useinstead ohos.data.relationalStore.RdbPredicates.lessThan + */ + lessThan(field: string, value: ValueType): RdbPredicates; + + /** + * Restricts the value of the field to be greater than or equal to the specified value. + * + * @param { string } field - Indicates the column name in the database table. + * @param { ValueType } value - Indicates the value to match with the {@link RdbPredicates}. + * @returns { RdbPredicates } - the SQL query statement with the specified {@link RdbPredicates}. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 7 + * @deprecated since 9 + * @useinstead ohos.data.relationalStore.RdbPredicates.greaterThanOrEqualTo + */ + greaterThanOrEqualTo(field: string, value: ValueType): RdbPredicates; + + /** + * Restricts the value of the field to be smaller than or equal to the specified value. + * + * @param { string } field - Indicates the column name in the database table. + * @param { ValueType } value - Indicates the value to match with the {@link RdbPredicates}. + * @returns { RdbPredicates } - the SQL query statement with the specified {@link RdbPredicates}. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 7 + * @deprecated since 9 + * @useinstead ohos.data.relationalStore.RdbPredicates.lessThanOrEqualTo + */ + lessThanOrEqualTo(field: string, value: ValueType): RdbPredicates; + + /** + * Restricts the ascending order of the return list. When there are several orders, + * the one close to the head has the highest priority. + * + * @param { string } field - Indicates the column name for sorting the return list. + * @returns { RdbPredicates } - the SQL query statement with the specified {@link RdbPredicates}. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 7 + * @deprecated since 9 + * @useinstead ohos.data.relationalStore.RdbPredicates.orderByAsc + */ + orderByAsc(field: string): RdbPredicates; + + /** + * Restricts the descending order of the return list. When there are several orders, + * the one close to the head has the highest priority. + * + * @param { string } field - Indicates the column name for sorting the return list. + * @returns { RdbPredicates } - the SQL query statement with the specified {@link RdbPredicates}. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 7 + * @deprecated since 9 + * @useinstead ohos.data.relationalStore.RdbPredicates.orderByDesc + */ + orderByDesc(field: string): RdbPredicates; + + /** + * Restricts each row of the query result to be unique. + * + * @returns { RdbPredicates } - the SQL query statement with the specified {@link RdbPredicates}. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 7 + * @deprecated since 9 + * @useinstead ohos.data.relationalStore.RdbPredicates.distinct + */ + distinct(): RdbPredicates; + + /** + * Restricts the max number of return records. + * + * @param { number } value - Indicates the max length of the return list. + * @returns { RdbPredicates } - the SQL query statement with the specified {@link RdbPredicates}. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 7 + * @deprecated since 9 + * @useinstead ohos.data.relationalStore.RdbPredicates.limitAs + */ + limitAs(value: number): RdbPredicates; + + /** + * Configure RdbPredicates to specify the start position of the returned result. + * Use this method together with limit(int). + * + * @param { number } rowOffset - Indicates the start position of the returned result. The value is a positive integer. + * @returns { RdbPredicates } - the SQL query statement with the specified {@link RdbPredicates}. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 7 + * @deprecated since 9 + * @useinstead ohos.data.relationalStore.RdbPredicates.offsetAs + */ + offsetAs(rowOffset: number): RdbPredicates; + + /** + * Configure RdbPredicates to group query results by specified columns. + * + * @param { Array } fields - Indicates the specified columns by which query results are grouped. + * @returns { RdbPredicates } - the SQL query statement with the specified {@link RdbPredicates}. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 7 + * @deprecated since 9 + * @useinstead ohos.data.relationalStore.RdbPredicates.groupBy + */ + groupBy(fields: Array): RdbPredicates; + + /** + * Configure RdbPredicates to specify the index column. + * Before using this method, you need to create an index column. + * + * @param { string } field - Indicates the name of the index column. + * @returns { RdbPredicates } - the SQL statement with the specified {@link RdbPredicates}. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 7 + * @deprecated since 9 + * @useinstead ohos.data.relationalStore.RdbPredicates.indexedBy + */ + indexedBy(field: string): RdbPredicates; + + /** + * Configure RdbPredicates to match the specified field whose data type is ValueType array and values + * are within a given range. + * + * @param { string } field - Indicates the column name in the database table. + * @param { Array } value - Indicates the values to match with {@link RdbPredicates}. + * @returns { RdbPredicates } - the SQL statement with the specified {@link RdbPredicates}. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 7 + * @deprecated since 9 + * @useinstead ohos.data.relationalStore.RdbPredicates.in + */ + in(field: string, value: Array): RdbPredicates; + + /** + * Configure RdbPredicates to match the specified field whose data type is ValueType array and values + * are out of a given range. + * + * @param { string } field - Indicates the column name in the database table. + * @param { Array } value - Indicates the values to match with {@link RdbPredicates}. + * @returns { RdbPredicates } - the SQL statement with the specified {@link RdbPredicates}. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 7 + * @deprecated since 9 + * @useinstead ohos.data.relationalStore.RdbPredicates.notIn + */ + notIn(field: string, value: Array): RdbPredicates; + } + + export type ResultSet = _ResultSet; +} + +export default rdb; diff --git a/relational_store/interfaces/inner_api/js/@ohos.data.relationalStore.d.ts b/relational_store/interfaces/inner_api/js/@ohos.data.relationalStore.d.ts new file mode 100644 index 00000000..952af0af --- /dev/null +++ b/relational_store/interfaces/inner_api/js/@ohos.data.relationalStore.d.ts @@ -0,0 +1,1860 @@ +/* + * 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. + */ + +import { AsyncCallback, Callback } from './@ohos.base'; +import Context from './application/BaseContext'; +import dataSharePredicates from './@ohos.data.dataSharePredicates'; + +/** + * Provides methods for rdbStore create and delete. + * + * @namespace relationalStore + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 9 + */ +declare namespace relationalStore { + /** + * Obtains a RDB store. + * You can set parameters of the RDB store as required. In general, this method is recommended + * to obtain a rdb store. + * + * @param { Context } context - indicates the context of application or capability. + * @param { StoreConfig } config - indicates the {@link StoreConfig} configuration of the database related to this RDB store. + * @param { AsyncCallback } callback - the RDB store {@link RdbStore}. + * @throws { BusinessError } 401 - if the parameter type is incorrect. + * @throws { BusinessError } 14800010 - if failed open database by invalid database name. + * @throws { BusinessError } 14800011 - if failed open database by database corrupted. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 9 + */ + function getRdbStore(context: Context, config: StoreConfig, callback: AsyncCallback): void; + + /** + * Obtains a RDB store. + * You can set parameters of the RDB store as required. In general, this method is recommended + * to obtain a rdb store. + * + * @param { Context } context - indicates the context of application or capability. + * @param { StoreConfig } config - indicates the {@link StoreConfig} configuration of the database related to this RDB store. + * @returns { Promise } the RDB store {@link RdbStore}. + * @throws { BusinessError } 401 - if the parameter type is incorrect. + * @throws { BusinessError } 14800010 - if failed open database by invalid database name. + * @throws { BusinessError } 14800011 - if failed open database by database corrupted. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 9 + */ + function getRdbStore(context: Context, config: StoreConfig): Promise; + + /** + * Deletes the database with a specified name. + * + * @param { Context } context - indicates the context of application or capability. + * @param { string } name - indicates the database name. + * @param { AsyncCallback } callback - the callback of deleteRdbStore. + * @throws { BusinessError } 401 - if the parameter type is incorrect. + * @throws { BusinessError } 14800010 - if failed delete database by invalid database name. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 9 + */ + function deleteRdbStore(context: Context, name: string, callback: AsyncCallback): void; + + /** + * Deletes the database with a specified name. + * + * @param { Context } context - indicates the context of application or capability. + * @param { string } name - indicates the database name. + * @returns { Promise } the promise returned by the function. + * @throws { BusinessError } 401 - if the parameter type is incorrect. + * @throws { BusinessError } 14800010 - if failed delete database by invalid database name. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 9 + */ + function deleteRdbStore(context: Context, name: string): Promise; + + /** + * Manages relational database configurations. + * + * @interface StoreConfig + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 9 + */ + interface StoreConfig { + /** + * The database name. + * + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 9 + */ + name: string; + + /** + * Specifies the security level of the database. + * + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 9 + */ + securityLevel: SecurityLevel; + + /** + * Specifies whether the database is encrypted. + * + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 9 + */ + encrypt?: boolean; + } + /** + * the cloud sync progress + * + * @enum { number } + * @syscap SystemCapability.DistributedDataManager.CloudSync.Client + * @since 10 + */ + enum Progress { + SYNC_BEGIN, + SYNC_IN_PROGRESS, + SYNC_FINISH, + } + + /** + * Describes the {@code RdbStore} type. + * + * @enum { number } + * @syscap SystemCapability.DistributedDataManager.CloudSync.Client + * @since 10 + */ + interface Statistic { + total: number; + success: number; + failed: number; + untreated: number; + } + /** + * Describes the {@code RdbStore} type. + * + * @enum { number } + * @syscap SystemCapability.DistributedDataManager.CloudSync.Client + * @since 10 + */ + interface ProgressDetail { + schedule : Progress; + code: number; + upload: Statistic; + download: Statistic; + } + + /** + * Describes the {@code RdbStore} type. + * + * @enum { number } + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 9 + */ + enum SecurityLevel { + /** + * S1: means the db is low level security + * There are some low impact, when the data is leaked. + * + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 9 + */ + S1 = 1, + + /** + * S2: means the db is middle level security + * There are some major impact, when the data is leaked. + * + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 9 + */ + S2 = 2, + + /** + * S3: means the db is high level security + * There are some severity impact, when the data is leaked. + * + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 9 + */ + S3 = 3, + + /** + * S4: means the db is critical level security + * There are some critical impact, when the data is leaked. + * + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 9 + */ + S4 = 4 + } + + /** + * Indicates possible value types + * + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 10 + */ + interface Asset { + name: string; + uri: string; + createTime: string; + modifyTime: string; + size: string; + } + + /** + * Indicates possible value types + * + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 9 + */ + type ValueType = number | string | boolean | Uint8Array | Asset | Asset[]; + + /** + * Values in buckets are stored in key-value pairs + * + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 9 + */ + type ValuesBucket = { [key:string]: ValueType | null; } + + /** + * Indicates the database synchronization mode. + * + * @enum { number } + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 9 + */ + enum SyncMode { + /** + * Indicates the data is pushed to remote device from local device. + * + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 9 + */ + SYNC_MODE_PUSH = 0, + + /** + * Indicates the data is pulled from remote device to local device. + * + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 9 + */ + SYNC_MODE_PULL = 1, + + /** + * Indicates the data is pulled from remote device to local device. + * + * @syscap SystemCapability.DistributedDataManager.CloudSync.Client + * @since 10 + */ + SYNC_MODE_TIME_FIRST, + + /** + * Indicates force push the native data to the cloud. + * + * @syscap SystemCapability.DistributedDataManager.CloudSync.Client + * @since 10 + */ + SYNC_MODE_NATIVE_FIRST, + + /** + * Indicates the data is pulled from remote device to local device. + * + * @syscap SystemCapability.DistributedDataManager.CloudSync.Client + * @since 10 + */ + SYNC_MODE_CLOUD_FIRST, + } + + /** + * Describes the subscription type. + * + * @permission ohos.permission.DISTRIBUTED_DATASYNC + * @enum { number } + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 9 + */ + enum SubscribeType { + /** + * Subscription to remote data changes + * + * @permission ohos.permission.DISTRIBUTED_DATASYNC + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 9 + */ + SUBSCRIBE_TYPE_REMOTE = 0 + } + + /** + * Describes the distributed type of the tables. + * + * @permission ohos.permission.DISTRIBUTED_DATASYNC + * @enum { number } + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 10 + */ + enum DistributedType { + /** + * distributed a range the devices + * + * @permission ohos.permission.DISTRIBUTED_DATASYNC + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 10 + */ + DISTRIBUTED_DEVICE, + + /** + * distributed by cloud + * + * @permission ohos.permission.DISTRIBUTED_DATASYNC + * @syscap SystemCapability.DistributedDataManager.CloudSync.Client + * @since 10 + */ + DISTRIBUTED_CLOUD + } + + /** + * Describes the conflict resolutions to insert data into the table. + * + * @enum { number } + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 10 + */ + enum ConflictResolution { + /** + * Implements no action when conflict occurs. + * + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 10 + */ + ON_CONFLICT_NONE = 0, + + /** + * Implements rollback operation when conflict occurs. + * + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 10 + */ + ON_CONFLICT_ROLLBACK = 1, + + /** + * Implements abort operation when conflict occurs. + * + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 10 + */ + ON_CONFLICT_ABORT = 2, + + /** + * Implements fail operation when conflict occurs. + * + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 10 + */ + ON_CONFLICT_FAIL = 3, + + /** + * Implements ignore operation when conflict occurs. + * + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 10 + */ + ON_CONFLICT_IGNORE = 4, + + /** + * Implements replace operation operator when conflict occurs. + * + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 10 + */ + ON_CONFLICT_REPLACE = 5 + } + + /** + * Provides methods for managing the relational database (RDB). + * This class provides methods for creating, querying, updating, and deleting RDBs. + * + * @interface RdbStore + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 9 + */ + interface RdbStore { + /** + * Obtains the RdbStore version. The version number must be an integer greater than 0. + * + * @throws { BusinessError } 401 - parameter error. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 10 + */ + version: number; + + /** + * Inserts a row of data into the target table. + * + * @param { string } table - indicates the target table. + * @param { ValuesBucket } values - indicates the row of data {@link ValuesBucket} to be inserted into the table. + * @param { AsyncCallback } callback - the row ID if the operation is successful. returns -1 otherwise. + * @throws { BusinessError } 401 - if the parameter type is incorrect. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 9 + */ + /** + * Inserts a row of data into the target table. + * + * @param { string } table - indicates the target table. + * @param { ValuesBucket } values - indicates the row of data {@link ValuesBucket} to be inserted into the table. + * @param { AsyncCallback } callback - the row ID if the operation is successful. returns -1 otherwise. + * @throws { BusinessError } 14800047 - if the WAL file size exceeds the default limit. + * @throws { BusinessError } 401 - if the parameter type is incorrect. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 10 + */ + insert(table: string, values: ValuesBucket, callback: AsyncCallback): void; + + /** + * Inserts a row of data into the target table. + * + * @param { string } table - indicates the target table. + * @param { ValuesBucket } values - indicates the row of data {@link ValuesBucket} to be inserted into the table. + * @param { ConflictResolution } conflict - indicates the {@link ConflictResolution} to insert data into the table. + * @param { AsyncCallback } callback - the row ID if the operation is successful. returns -1 otherwise. + * @throws { BusinessError } 14800047 - if the WAL file size exceeds the default limit. + * @throws { BusinessError } 401 - if the parameter type is incorrect. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 10 + */ + insert(table: string, values: ValuesBucket, conflict: ConflictResolution, callback: AsyncCallback): void; + + /** + * Inserts a row of data into the target table. + * + * @param { string } table - indicates the target table. + * @param { ValuesBucket } values - indicates the row of data {@link ValuesBucket} to be inserted into the table. + * @returns { Promise } the row ID if the operation is successful. return -1 otherwise. + * @throws { BusinessError } 401 - if the parameter type is incorrect. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 9 + */ + /** + * Inserts a row of data into the target table. + * + * @param { string } table - indicates the target table. + * @param { ValuesBucket } values - indicates the row of data {@link ValuesBucket} to be inserted into the table. + * @returns { Promise } the row ID if the operation is successful. return -1 otherwise. + * @throws { BusinessError } 14800047 - if the WAL file size exceeds the default limit. + * @throws { BusinessError } 401 - if the parameter type is incorrect. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 10 + */ + insert(table: string, values: ValuesBucket): Promise; + + /** + * Inserts a row of data into the target table. + * + * @param { string } table - indicates the target table. + * @param { ValuesBucket } values - indicates the row of data {@link ValuesBucket} to be inserted into the table. + * @param { ConflictResolution } conflict - indicates the {@link ConflictResolution} to insert data into the table. + * @returns { Promise } the row ID if the operation is successful. return -1 otherwise. + * @throws { BusinessError } 14800047 - if the WAL file size exceeds the default limit. + * @throws { BusinessError } 401 - if the parameter type is incorrect. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 10 + */ + insert(table: string, values: ValuesBucket, conflict: ConflictResolution): Promise; + + /** + * Inserts a batch of data into the target table. + * + * @param { string } table - indicates the target table. + * @param { Array } values - indicates the rows of data {@link ValuesBucket} to be inserted into the table. + * @param { AsyncCallback } callback - the number of values that were inserted if the operation is successful. returns -1 otherwise. + * @throws { BusinessError } 401 - if the parameter type is incorrect. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 9 + */ + /** + * Inserts a batch of data into the target table. + * + * @param { string } table - indicates the target table. + * @param { Array } values - indicates the rows of data {@link ValuesBucket} to be inserted into the table. + * @param { AsyncCallback } callback - the number of values that were inserted if the operation is successful. returns -1 otherwise. + * @throws { BusinessError } 14800047 - if the WAL file size exceeds the default limit. + * @throws { BusinessError } 401 - if the parameter type is incorrect. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 10 + */ + batchInsert(table: string, values: Array, callback: AsyncCallback): void; + + /** + * Inserts a batch of data into the target table. + * + * @param { string } table - indicates the target table. + * @param { Array } values - indicates the rows of data {@link ValuesBucket} to be inserted into the table. + * @returns { Promise } the number of values that were inserted if the operation is successful. returns -1 otherwise. + * @throws { BusinessError } 401 - if the parameter type is incorrect. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 9 + */ + /** + * Inserts a batch of data into the target table. + * + * @param { string } table - indicates the target table. + * @param { Array } values - indicates the rows of data {@link ValuesBucket} to be inserted into the table. + * @returns { Promise } the number of values that were inserted if the operation is successful. returns -1 otherwise. + * @throws { BusinessError } 14800047 - if the WAL file size exceeds the default limit. + * @throws { BusinessError } 401 - if the parameter type is incorrect. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 10 + */ + batchInsert(table: string, values: Array): Promise; + + /** + * Updates data in the database based on a specified instance object of RdbPredicates. + * + * @param { ValuesBucket } 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 { RdbPredicates } predicates - indicates the specified update condition by the instance object of {@link RdbPredicates}. + * @param { AsyncCallback } callback - the number of affected rows. + * @throws { BusinessError } 401 - if the parameter type is incorrect. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 9 + */ + /** + * Updates data in the database based on a specified instance object of RdbPredicates. + * + * @param { ValuesBucket } 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 { RdbPredicates } predicates - indicates the specified update condition by the instance object of {@link RdbPredicates}. + * @param { AsyncCallback } callback - the number of affected rows. + * @throws { BusinessError } 14800047 - if the WAL file size exceeds the default limit. + * @throws { BusinessError } 401 - if the parameter type is incorrect. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 10 + */ + update(values: ValuesBucket, predicates: RdbPredicates, callback: AsyncCallback): void; + + /** + * Updates data in the database based on a specified instance object of RdbPredicates. + * + * @param { ValuesBucket } 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 { RdbPredicates } predicates - indicates the specified update condition by the instance object of {@link RdbPredicates}. + * @param { ConflictResolution } conflict - indicates the {@link ConflictResolution} to insert data into the table. + * @param { AsyncCallback } callback - the number of affected rows. + * @throws { BusinessError } 14800047 - if the WAL file size exceeds the default limit. + * @throws { BusinessError } 401 - if the parameter type is incorrect. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 10 + */ + update( + values: ValuesBucket, + predicates: RdbPredicates, + conflict: ConflictResolution, + callback: AsyncCallback + ): void; + + /** + * Updates data in the database based on a specified instance object of RdbPredicates. + * + * @param { ValuesBucket } 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 { RdbPredicates } predicates - indicates the specified update condition by the instance object of {@link RdbPredicates}. + * @returns { Promise } the number of affected rows. + * @throws { BusinessError } 401 - if the parameter type is incorrect. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 9 + */ + /** + * Updates data in the database based on a specified instance object of RdbPredicates. + * + * @param { ValuesBucket } 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 { RdbPredicates } predicates - indicates the specified update condition by the instance object of {@link RdbPredicates}. + * @returns { Promise } the number of affected rows. + * @throws { BusinessError } 14800047 - if the WAL file size exceeds the default limit. + * @throws { BusinessError } 401 - if the parameter type is incorrect. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 10 + */ + update(values: ValuesBucket, predicates: RdbPredicates): Promise; + + /** + * Updates data in the database based on a specified instance object of RdbPredicates. + * + * @param { ValuesBucket } 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 { RdbPredicates } predicates - indicates the specified update condition by the instance object of {@link RdbPredicates}. + * @param { ConflictResolution } conflict - indicates the {@link ConflictResolution} to insert data into the table. + * @returns { Promise } the number of affected rows. + * @throws { BusinessError } 14800047 - if the WAL file size exceeds the default limit. + * @throws { BusinessError } 401 - if the parameter type is incorrect. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 10 + */ + update(values: ValuesBucket, predicates: RdbPredicates, conflict: ConflictResolution): Promise; + + /** + * Updates data in the database based on a specified instance object of RdbPredicates. + * + * @param { string } table - indicates the target table. + * @param { ValuesBucket } 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 { dataSharePredicates.DataSharePredicates } predicates - indicates the specified update condition by the instance object of {@link dataSharePredicates.DataSharePredicates}. + * @param { AsyncCallback } callback - the number of affected rows. + * @throws { BusinessError } 401 - if the parameter type is incorrect. + * @throws { BusinessError } 202 - if permission verification failed, application which is not a system application uses system API. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @systemapi + * @StageModelOnly + * @since 9 + */ + /** + * Updates data in the database based on a specified instance object of RdbPredicates. + * + * @param { string } table - indicates the target table. + * @param { ValuesBucket } 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 { dataSharePredicates.DataSharePredicates } predicates - indicates the specified update condition by the instance object of {@link dataSharePredicates.DataSharePredicates}. + * @param { AsyncCallback } callback - the number of affected rows. + * @throws { BusinessError } 14800047 - if the WAL file size exceeds the default limit. + * @throws { BusinessError } 401 - if the parameter type is incorrect. + * @throws { BusinessError } 202 - if permission verification failed, application which is not a system application uses system API. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @systemapi + * @StageModelOnly + * @since 10 + */ + update( + table: string, + values: ValuesBucket, + predicates: dataSharePredicates.DataSharePredicates, + callback: AsyncCallback + ): void; + + /** + * Updates data in the database based on a specified instance object of RdbPredicates. + * + * @param { string } table - indicates the target table. + * @param { ValuesBucket } 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 { dataSharePredicates.DataSharePredicates } predicates - indicates the specified update condition by the instance object of {@link dataSharePredicates.DataSharePredicates}. + * @returns { Promise } the number of affected rows. + * @throws { BusinessError } 401 - if the parameter type is incorrect. + * @throws { BusinessError } 202 - if permission verification failed, application which is not a system application uses system API. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @systemapi + * @StageModelOnly + * @since 9 + */ + /** + * Updates data in the database based on a specified instance object of RdbPredicates. + * + * @param { string } table - indicates the target table. + * @param { ValuesBucket } 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 { dataSharePredicates.DataSharePredicates } predicates - indicates the specified update condition by the instance object of {@link dataSharePredicates.DataSharePredicates}. + * @returns { Promise } the number of affected rows. + * @throws { BusinessError } 14800047 - if the WAL file size exceeds the default limit. + * @throws { BusinessError } 401 - if the parameter type is incorrect. + * @throws { BusinessError } 202 - if permission verification failed, application which is not a system application uses system API. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @systemapi + * @StageModelOnly + * @since 10 + */ + update(table: string, values: ValuesBucket, predicates: dataSharePredicates.DataSharePredicates): Promise; + + /** + * Deletes data from the database based on a specified instance object of RdbPredicates. + * + * @param { RdbPredicates } predicates - the specified delete condition by the instance object of {@link RdbPredicates}. + * @param { AsyncCallback } callback - the number of affected rows. + * @throws { BusinessError } 401 - if the parameter type is incorrect. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 9 + */ + /** + * Deletes data from the database based on a specified instance object of RdbPredicates. + * + * @param { RdbPredicates } predicates - the specified delete condition by the instance object of {@link RdbPredicates}. + * @param { AsyncCallback } callback - the number of affected rows. + * @throws { BusinessError } 14800047 - if the WAL file size exceeds the default limit. + * @throws { BusinessError } 401 - if the parameter type is incorrect. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 10 + */ + delete(predicates: RdbPredicates, callback: AsyncCallback): void; + + /** + * Deletes data from the database based on a specified instance object of RdbPredicates. + * + * @param { RdbPredicates } predicates - the specified delete condition by the instance object of {@link RdbPredicates}. + * @returns { Promise } the number of affected rows. + * @throws { BusinessError } 401 - if the parameter type is incorrect. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 9 + */ + /** + * Deletes data from the database based on a specified instance object of RdbPredicates. + * + * @param { RdbPredicates } predicates - the specified delete condition by the instance object of {@link RdbPredicates}. + * @returns { Promise } return the number of affected rows. + * @throws { BusinessError } 14800047 - if the WAL file size exceeds the default limit. + * @throws { BusinessError } 401 - if the parameter type is incorrect. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 10 + */ + delete(predicates: RdbPredicates): Promise; + + /** + * Deletes data from the database based on a specified instance object of RdbPredicates. + * + * @param { string } table - indicates the target table. + * @param { dataSharePredicates.DataSharePredicates } predicates - the specified delete condition by the instance object of {@link dataSharePredicates.DataSharePredicates}. + * @param { AsyncCallback } callback - the number of affected rows. + * @throws { BusinessError } 401 - if the parameter type is incorrect. + * @throws { BusinessError } 202 - if permission verification failed, application which is not a system application uses system API. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @systemapi + * @StageModelOnly + * @since 9 + */ + /** + * Deletes data from the database based on a specified instance object of RdbPredicates. + * + * @param { string } table - indicates the target table. + * @param { dataSharePredicates.DataSharePredicates } predicates - the specified delete condition by the instance object of {@link dataSharePredicates.DataSharePredicates}. + * @param { AsyncCallback } callback - the number of affected rows. + * @throws { BusinessError } 14800047 - if the WAL file size exceeds the default limit. + * @throws { BusinessError } 401 - if the parameter type is incorrect. + * @throws { BusinessError } 202 - if permission verification failed, application which is not a system application uses system API. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @systemapi + * @StageModelOnly + * @since 10 + */ + delete(table: string, predicates: dataSharePredicates.DataSharePredicates, callback: AsyncCallback): void; + + /** + * Deletes data from the database based on a specified instance object of RdbPredicates. + * + * @param { string } table - indicates the target table. + * @param { dataSharePredicates.DataSharePredicates } predicates - the specified delete condition by the instance object of {@link dataSharePredicates.DataSharePredicates}. + * @returns { Promise } the number of affected rows. + * @throws { BusinessError } 401 - if the parameter type is incorrect. + * @throws { BusinessError } 202 - if permission verification failed, application which is not a system application uses system API. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @systemapi + * @StageModelOnly + * @since 9 + */ + /** + * Deletes data from the database based on a specified instance object of RdbPredicates. + * + * @param { string } table - indicates the target table. + * @param { dataSharePredicates.DataSharePredicates } predicates - the specified delete condition by the instance object of {@link dataSharePredicates.DataSharePredicates}. + * @returns { Promise } the number of affected rows. + * @throws { BusinessError } 14800047 - if the WAL file size exceeds the default limit. + * @throws { BusinessError } 401 - if the parameter type is incorrect. + * @throws { BusinessError } 202 - if permission verification failed, application which is not a system application uses system API. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @systemapi + * @StageModelOnly + * @since 10 + */ + delete(table: string, predicates: dataSharePredicates.DataSharePredicates): Promise; + + /** + * Queries data in the database based on specified conditions. + * + * @param { RdbPredicates } predicates - the specified query condition by the instance object of {@link RdbPredicates}. + * @param { Array } columns - the columns to query. If the value is empty array, the query applies to all columns. + * @param { AsyncCallback } callback - the {@link ResultSet} object if the operation is successful. + * @throws { BusinessError } 401 - if the parameter type is incorrect. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 9 + */ + query(predicates: RdbPredicates, columns: Array, callback: AsyncCallback): void; + + /** + * Queries data in the database based on specified conditions. + * + * @param { RdbPredicates } predicates - the specified query condition by the instance object of {@link RdbPredicates}. + * @param { Array } columns - the columns to query. If the value is null, the query applies to all columns. + * @returns { Promise } the {@link ResultSet} object if the operation is successful. + * @throws { BusinessError } 401 - if the parameter type is incorrect. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 9 + */ + query(predicates: RdbPredicates, columns?: Array): Promise; + + /** + * Queries data in the database based on specified conditions. + * + * @param { string } table - indicates the target table. + * @param { dataSharePredicates.DataSharePredicates } predicates - the specified query condition by the instance object of {@link dataSharePredicates.DataSharePredicates}. + * @param { Array } columns - the columns to query. If the value is empty array, the query applies to all columns. + * @param { AsyncCallback } callback - the {@link ResultSet} object if the operation is successful. + * @throws { BusinessError } 401 - if the parameter type is incorrect. + * @throws { BusinessError } 202 - if permission verification failed, application which is not a system application uses system API. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @systemapi + * @StageModelOnly + * @since 9 + */ + query( + table: string, + predicates: dataSharePredicates.DataSharePredicates, + columns: Array, + callback: AsyncCallback + ): void; + + /** + * Queries data in the database based on specified conditions. + * + * @param { string } table - indicates the target table. + * @param { dataSharePredicates.DataSharePredicates } predicates - the specified query condition by the instance object of {@link dataSharePredicates.DataSharePredicates}. + * @param { Array } columns - the columns to query. If the value is null, the query applies to all columns. + * @returns { Promise } the {@link ResultSet} object if the operation is successful. + * @throws { BusinessError } 401 - if the parameter type is incorrect. + * @throws { BusinessError } 202 - if permission verification failed, application which is not a system application uses system API. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @systemapi + * @StageModelOnly + * @since 9 + */ + query( + table: string, + predicates: dataSharePredicates.DataSharePredicates, + columns?: Array + ): Promise; + + /** + * Queries data in the database based on SQL statement. + * + * @param { string } sql - indicates the SQL statement to execute. + * @param { Array } bindArgs - indicates the {@link ValueType} values of the parameters in the SQL statement. The values are strings. + * @param { AsyncCallback } callback - the {@link ResultSet} object if the operation is successful. + * @throws { BusinessError } 401 - if the parameter type is incorrect. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 9 + */ + querySql(sql: string, bindArgs: Array, callback: AsyncCallback): void; + + /** + * Queries data in the database based on SQL statement. + * + * @param { string } sql - indicates the SQL statement to execute. + * @param { Array } bindArgs - indicates the {@link ValueType} values of the parameters in the SQL statement. The values are strings. + * @returns { Promise } the {@link ResultSet} object if the operation is successful. + * @throws { BusinessError } 401 - if the parameter type is incorrect. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 9 + */ + querySql(sql: string, bindArgs?: Array): Promise; + + /** + * Executes a SQL statement that contains specified parameters but returns no value. + * + * @param { string } sql - indicates the SQL statement to execute. + * @param { Array } bindArgs - indicates the {@link ValueType} values of the parameters in the SQL statement. The values are strings. + * @param { AsyncCallback } callback - the callback of executeSql. + * @throws { BusinessError } 401 - if the parameter type is incorrect. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 9 + */ + /** + * Executes a SQL statement that contains specified parameters but returns no value. + * + * @param { string } sql - indicates the SQL statement to execute. + * @param { Array } bindArgs - indicates the {@link ValueType} values of the parameters in the SQL statement. The values are strings. + * @param { AsyncCallback } callback - the callback of executeSql. + * @throws { BusinessError } 14800047 - if the WAL file size exceeds the default limit. + * @throws { BusinessError } 401 - if the parameter type is incorrect. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 10 + */ + executeSql(sql: string, bindArgs: Array, callback: AsyncCallback): void; + + /** + * Executes a SQL statement that contains specified parameters but returns no value. + * + * @param { string } sql - indicates the SQL statement to execute. + * @param { Array } bindArgs - indicates the {@link ValueType} values of the parameters in the SQL statement. The values are strings. + * @returns { Promise } the promise returned by the function. + * @throws { BusinessError } 401 - if the parameter type is incorrect. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 9 + */ + /** + * Executes a SQL statement that contains specified parameters but returns no value. + * + * @param { string } sql - indicates the SQL statement to execute. + * @param { Array } bindArgs - indicates the {@link ValueType} values of the parameters in the SQL statement. The values are strings. + * @returns { Promise } the promise returned by the function. + * @throws { BusinessError } 14800047 - if the WAL file size exceeds the default limit. + * @throws { BusinessError } 401 - if the parameter type is incorrect. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 10 + */ + executeSql(sql: string, bindArgs?: Array): Promise; + + /** + * BeginTransaction before execute your sql. + * + * @throws { BusinessError } 401 - if the parameter type is incorrect. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 9 + */ + /** + * BeginTransaction before execute your sql. + * + * @throws { BusinessError } 14800047 - if the WAL file size exceeds the default limit. + * @throws { BusinessError } 401 - if the parameter type is incorrect. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 10 + */ + beginTransaction(): void; + + /** + * Commit the the sql you have executed. + * + * @throws { BusinessError } 401 - if the parameter type is incorrect. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 9 + */ + commit(): void; + + /** + * Roll back the sql you have already executed. + * + * @throws { BusinessError } 401 - if the parameter type is incorrect. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 9 + */ + rollBack(): void; + + /** + * Backs up a database in a specified name. + * + * @param { string } destName - indicates the name that saves the database backup. + * @param { AsyncCallback } callback - the callback of backup. + * @throws { BusinessError } 401 - if the parameter type is incorrect. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 9 + */ + backup(destName: string, callback: AsyncCallback): void; + + /** + * Backs up a database in a specified name. + * + * @param { string } destName - indicates the name that saves the database backup. + * @returns { Promise } the promise returned by the function. + * @throws { BusinessError } 401 - if the parameter type is incorrect. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 9 + */ + backup(destName: string): Promise; + + /** + * Restores a database from a specified database file. + * + * @param { string } srcName - indicates the name that saves the database file. + * @param { AsyncCallback } callback - the callback of restore. + * @throws { BusinessError } 401 - if the parameter type is incorrect. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 9 + */ + restore(srcName: string, callback: AsyncCallback): void; + + /** + * Restores a database from a specified database file. + * + * @param { string } srcName - indicates the name that saves the database file. + * @returns { Promise } the promise returned by the function. + * @throws { BusinessError } 401 - if the parameter type is incorrect. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 9 + */ + restore(srcName: string): Promise; + + /** + * Set table to be distributed table. + * + * @permission ohos.permission.DISTRIBUTED_DATASYNC + * @param { Array } tables - indicates the tables name you want to set. + * @param { AsyncCallback } callback - the callback of setDistributedTables. + * @throws { BusinessError } 401 - if the parameter type is incorrect. + * @throws { BusinessError } 801 - Capability not supported. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 9 + */ + setDistributedTables(tables: Array, callback: AsyncCallback): void; + + /** + * Set table to be distributed table. + * + * @permission ohos.permission.DISTRIBUTED_DATASYNC + * @param { Array } tables - indicates the tables name you want to set. + * @param { number } mode - indicates the tables distributed type {@link DistributedType}. + * @param { AsyncCallback } callback - the callback of setDistributedTables. + * @throws { BusinessError } 401 - if the parameter type is incorrect. + * @throws { BusinessError } 801 - Capability not supported. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 10 + */ + setDistributedTables(tables: Array, type: number, callback: AsyncCallback): void; + + /** + * Set table to be distributed table. + * + * @permission ohos.permission.DISTRIBUTED_DATASYNC + * @param { Array } tables - indicates the tables name you want to set. + * @param { number } mode - indicates the tables distributed type {@link DistributedType}. + * @returns { Promise } the promise returned by the function. + * @throws { BusinessError } 401 - if the parameter type is incorrect. + * @throws { BusinessError } 801 - Capability not supported. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 9 + */ + setDistributedTables(tables: Array, type?: number): Promise; + + /** + * Obtain distributed table name of specified remote device according to local table name. + * When query remote device database, distributed table name is needed. + * + * @permission ohos.permission.DISTRIBUTED_DATASYNC + * @param { string } device - indicates the remote device. + * @param { string } table - {string}: the distributed table name. + * @param { AsyncCallback } callback + * @throws { BusinessError } 401 - if the parameter type is incorrect. + * @throws { BusinessError } 801 - Capability not supported. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 9 + */ + obtainDistributedTableName(device: string, table: string, callback: AsyncCallback): void; + + /** + * Obtain distributed table name of specified remote device according to local table name. + * When query remote device database, distributed table name is needed. + * + * @permission ohos.permission.DISTRIBUTED_DATASYNC + * @param { string } device - indicates the remote device. + * @param { string } table + * @returns { Promise } {string}: the distributed table name. + * @throws { BusinessError } 401 - if the parameter type is incorrect. + * @throws { BusinessError } 801 - Capability not supported. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 9 + */ + obtainDistributedTableName(device: string, table: string): Promise; + + /** + * Sync data between devices. + * + * @permission ohos.permission.DISTRIBUTED_DATASYNC + * @param { SyncMode } mode - indicates the database synchronization mode. + * @param { RdbPredicates } predicates - the specified sync condition by the instance object of {@link RdbPredicates}. + * @param { AsyncCallback> } callback - {Array<[string, number]>}: devices sync status array, {string}: device id, {number}: device sync status. + * @throws { BusinessError } 401 - if the parameter type is incorrect. + * @throws { BusinessError } 801 - Capability not supported. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 9 + */ + sync(mode: SyncMode, predicates: RdbPredicates, callback: AsyncCallback>): void; + + /** + * Sync data between devices. + * + * @permission ohos.permission.DISTRIBUTED_DATASYNC + * @param { SyncMode } mode - indicates the database synchronization mode. + * @param { RdbPredicates } predicates - the specified sync condition by the instance object of {@link RdbPredicates}. + * @returns { Promise> } {Array<[string, number]>}: devices sync status array, {string}: device id, {number}: device sync status. + * @throws { BusinessError } 401 - if the parameter type is incorrect. + * @throws { BusinessError } 801 - Capability not supported. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 9 + */ + sync(mode: SyncMode, predicates: RdbPredicates): Promise>; + + /** + * Sync data to cloud. + * + * @permission ohos.permission.DISTRIBUTED_DATASYNC + * @param { number } mode - indicates the database synchronization mode. + * @param { Callback } progress - the specified sync condition by the instance object of {@link ProgressDetail}. + * @param { AsyncCallback } callback - {Array<[string, number]>}: devices sync status array, {string}: device id, {number}: device sync status. + * @throws { BusinessError } 401 - if the parameter type is incorrect. + * @throws { BusinessError } 801 - Capability not supported. + * @syscap SystemCapability.DistributedDataManager.CloudSync.Client + * @since 10 + */ + cloudSync(mode: SyncMode, progress: Callback, callback: AsyncCallback): void; + + /** + * Sync data to cloud. + * + * @permission ohos.permission.DISTRIBUTED_DATASYNC + * @param { number } mode - indicates the database synchronization mode. + * @param { Callback } progress - the specified sync condition by the instance object of {@link ProgressDetail}. + * @returns { Promise } : devices sync status array, {string}: device id, {number}: device sync status. + * @throws { BusinessError } 401 - if the parameter type is incorrect. + * @throws { BusinessError } 801 - Capability not supported. + * @syscap SystemCapability.DistributedDataManager.CloudSync.Client + * @since 10 + */ + cloudSync(mode: SyncMode, progress: Callback): Promise; + + /** + * Sync data to cloud. + * + * @permission ohos.permission.DISTRIBUTED_DATASYNC + * @param { number } mode - indicates the database synchronization mode. + * @param { string[] } tables - indicates the database synchronization mode. + * @param { Callback } progress - the specified sync condition by the instance object of {@link ProgressDetail}. + * @param { AsyncCallback } callback - {Array<[string, number]>}: devices sync status array, {string}: device id, {number}: device sync status. + * @throws { BusinessError } 401 - if the parameter type is incorrect. + * @throws { BusinessError } 801 - Capability not supported. + * @syscap SystemCapability.DistributedDataManager.CloudSync.Client + * @since 10 + */ + cloudSync(mode: SyncMode, tables: string[], progress: Callback, callback: AsyncCallback): void; + + /** + * Sync data to cloud. + * + * @permission ohos.permission.DISTRIBUTED_DATASYNC + * @param { number } mode - indicates the database synchronization mode. + * @param { string[] } tables - indicates the database synchronization mode. + * @param { Callback } progress - the specified sync condition by the instance object of {@link ProgressDetail}. + * @returns { Promise } : devices sync status array, {string}: device id, {number}: device sync status. + * @throws { BusinessError } 401 - if the parameter type is incorrect. + * @throws { BusinessError } 801 - Capability not supported. + * @syscap SystemCapability.DistributedDataManager.CloudSync.Client + * @since 10 + */ + cloudSync(mode: SyncMode, tables: string[], progress: Callback): Promise; + + /** + * Queries remote data in the database based on specified conditions before Synchronizing Data. + * + * @param { string } device - indicates specified remote device. + * @param { string } table - indicates the target table. + * @param { RdbPredicates } predicates - the specified remote remote query condition by the instance object of {@link RdbPredicates}. + * @param { Array } columns - the columns to remote query. If the value is empty array, the remote query applies to all columns. + * @param { AsyncCallback } callback - the {@link ResultSet} object if the operation is successful. + * @throws { BusinessError } 401 - if the parameter type is incorrect. + * @throws { BusinessError } 801 - Capability not supported. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 9 + */ + remoteQuery( + device: string, + table: string, + predicates: RdbPredicates, + columns: Array, + callback: AsyncCallback + ): void; + + /** + * Queries remote data in the database based on specified conditions before Synchronizing Data. + * + * @param { string } device - indicates specified remote device. + * @param { string } table - indicates the target table. + * @param { RdbPredicates } predicates - the specified remote remote query condition by the instance object of {@link RdbPredicates}. + * @param { Array } columns - the columns to remote query. If the value is empty array, the remote query applies to all columns. + * @returns { Promise } the {@link ResultSet} object if the operation is successful. + * @throws { BusinessError } 401 - if the parameter type is incorrect. + * @throws { BusinessError } 801 - Capability not supported. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 9 + */ + remoteQuery(device: string, table: string, predicates: RdbPredicates, columns: Array): Promise; + + /** + * Registers an observer for the database. When data in the distributed database changes, + * the callback will be invoked. + * + * @param { 'dataChange' } event - indicates the event must be string 'dataChange'. + * @param { SubscribeType } type - indicates the subscription type, which is defined in {@link SubscribeType}.If its value is SUBSCRIBE_TYPE_REMOTE, ohos.permission.DISTRIBUTED_DATASYNC is required. + * @param { Callback> } observer - {Array}: the observer of data change events in the distributed database. + * @throws { BusinessError } 401 - if the parameter type is incorrect. + * @throws { BusinessError } 801 - Capability not supported. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 9 + */ + on(event: 'dataChange', type: SubscribeType, observer: Callback>): void; + + /** + * Remove specified observer of specified type from the database. + * + * @param { 'dataChange' } event - indicates the event must be string 'dataChange'. + * @param { SubscribeType } type - indicates the subscription type, which is defined in {@link SubscribeType}.If its value is SUBSCRIBE_TYPE_REMOTE, ohos.permission.DISTRIBUTED_DATASYNC is required. + * @param { Callback> } observer - {Array}: the data change observer already registered. + * @throws { BusinessError } 401 - if the parameter type is incorrect. + * @throws { BusinessError } 801 - Capability not supported. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 9 + */ + off(event: 'dataChange', type: SubscribeType, observer: Callback>): void; + } + + /** + * Manages relational database configurations. + * + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 9 + */ + class RdbPredicates { + /** + * A parameterized constructor used to create a RdbPredicates instance. + * + * @param { string } name - indicates the table name of the database. + * @throws { BusinessError } 401 - if the parameter type is incorrect. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 9 + */ + constructor(name: string); + + /** + * Specifies remote devices which connect to local device when syncing distributed database. + * When query database, this function should not be called. + * + * @param { Array } devices - indicates specified remote devices. + * @returns { RdbPredicates } - the {@link RdbPredicates} self. + * @throws { BusinessError } 401 - if the parameter type is incorrect. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 9 + */ + inDevices(devices: Array): RdbPredicates; + + /** + * Specifies all remote devices which connect to local device when syncing distributed database. + * When query database, this function should not be called. + * + * @returns { RdbPredicates } - the {@link RdbPredicates} self. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 9 + */ + inAllDevices(): RdbPredicates; + + /** + * Configure the RdbPredicates to match the field whose data type is ValueType and value is equal + * to a specified value. + * This method is similar to = of the SQL statement. + * + * @param { string } field - indicates the column name in the database table. + * @param { ValueType } value - indicates the value to match with the {@link RdbPredicates}. + * @returns { RdbPredicates } - the {@link RdbPredicates} self. + * @throws { BusinessError } 401 - if the parameter type is incorrect. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 9 + */ + equalTo(field: string, value: ValueType): RdbPredicates; + + /** + * Configure the RdbPredicates to match the field whose data type is ValueType and value is not equal to + * a specified value. + * This method is similar to != of the SQL statement. + * + * @param { string } field - indicates the column name in the database table. + * @param { ValueType } value - indicates the value to match with the {@link RdbPredicates}. + * @returns { RdbPredicates } - the {@link RdbPredicates} self. + * @throws { BusinessError } 401 - if the parameter type is incorrect. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 9 + */ + notEqualTo(field: string, value: ValueType): RdbPredicates; + + /** + * Adds a left parenthesis to the RdbPredicates. + * This method is similar to ( of the SQL statement and needs to be used together with endWrap(). + * + * @returns { RdbPredicates } - the {@link RdbPredicates} with the left parenthesis. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 9 + */ + beginWrap(): RdbPredicates; + + /** + * Adds a right parenthesis to the RdbPredicates. + * This method is similar to ) of the SQL statement and needs to be used together with beginWrap(). + * + * @returns { RdbPredicates } - the {@link RdbPredicates} with the right parenthesis. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 9 + */ + endWrap(): RdbPredicates; + + /** + * Adds an or condition to the RdbPredicates. + * This method is similar to or of the SQL statement. + * + * @returns { RdbPredicates } - the {@link RdbPredicates} with the or condition. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 9 + */ + or(): RdbPredicates; + + /** + * Adds an and condition to the RdbPredicates. + * This method is similar to and of the SQL statement. + * + * @returns { RdbPredicates } - the {@link RdbPredicates} with the and condition. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 9 + */ + and(): RdbPredicates; + + /** + * Configure the RdbPredicates to match the field whose data type is string and value + * contains a specified value. + * This method is similar to contains of the SQL statement. + * + * @param { string } field - indicates the column name in the database table. + * @param { string } value - indicates the value to match with the {@link RdbPredicates}. + * @returns { RdbPredicates } - the {@link RdbPredicates} self. + * @throws { BusinessError } 401 - if the parameter type is incorrect. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 9 + */ + contains(field: string, value: string): RdbPredicates; + + /** + * Configure the RdbPredicates to match the field whose data type is string and value starts + * with a specified string. + * This method is similar to value% of the SQL statement. + * + * @param { string } field - indicates the column name in the database table. + * @param { string } value - indicates the value to match with the {@link RdbPredicates}. + * @returns { RdbPredicates } - the {@link RdbPredicates} self. + * @throws { BusinessError } 401 - if the parameter type is incorrect. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 9 + */ + beginsWith(field: string, value: string): RdbPredicates; + + /** + * Configure the RdbPredicates to match the field whose data type is string and value + * ends with a specified string. + * This method is similar to %value of the SQL statement. + * + * @param { string } field - indicates the column name in the database table. + * @param { string } value - indicates the value to match with the {@link RdbPredicates}. + * @returns { RdbPredicates } - the {@link RdbPredicates} self. + * @throws { BusinessError } 401 - if the parameter type is incorrect. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 9 + */ + endsWith(field: string, value: string): RdbPredicates; + + /** + * Configure the RdbPredicates to match the fields whose value is null. + * This method is similar to is null of the SQL statement. + * + * @param { string } field - indicates the column name in the database table. + * @returns { RdbPredicates } - the {@link RdbPredicates} self. + * @throws { BusinessError } 401 - if the parameter type is incorrect. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 9 + */ + isNull(field: string): RdbPredicates; + + /** + * Configure the RdbPredicates to match the specified fields whose value is not null. + * This method is similar to is not null of the SQL statement. + * + * @param { string } field - indicates the column name in the database table. + * @returns { RdbPredicates } - the {@link RdbPredicates} self. + * @throws { BusinessError } 401 - if the parameter type is incorrect. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 9 + */ + isNotNull(field: string): RdbPredicates; + + /** + * Configure the RdbPredicates to match the fields whose data type is string and value is + * similar to a specified string. + * This method is similar to like of the SQL statement. + * + * @param { string } field - indicates the column name in the database table. + * @param { string } value - indicates the value to match with the {@link RdbPredicates}. + * @returns { RdbPredicates } - the {@link RdbPredicates} that match the specified field. + * @throws { BusinessError } 401 - if the parameter type is incorrect. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 9 + */ + like(field: string, value: string): RdbPredicates; + + /** + * Configure RdbPredicates to match the specified field whose data type is string and the value contains + * a wildcard. + * Different from like, the input parameters of this method are case-sensitive. + * + * @param { string } field - indicates the column name in the database table. + * @param { string } value - indicates the value to match with the {@link RdbPredicates}. + * @returns { RdbPredicates } - the SQL statement with the specified {@link RdbPredicates}. + * @throws { BusinessError } 401 - if the parameter type is incorrect. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 9 + */ + glob(field: string, value: string): RdbPredicates; + + /** + * Configure RdbPredicates to match the specified field whose value is within a given range. + * + * @param { string } field - indicates the column name. + * @param { ValueType } low - indicates the minimum value. + * @param { ValueType } high - indicates the maximum value. + * @returns { RdbPredicates } - the SQL statement with the specified {@link RdbPredicates}. + * @throws { BusinessError } 401 - if the parameter type is incorrect. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 9 + */ + between(field: string, low: ValueType, high: ValueType): RdbPredicates; + + /** + * Configure RdbPredicates to match the specified field whose value is out of a given range. + * + * @param { string } field - indicates the column name in the database table. + * @param { ValueType } low - indicates the minimum value. + * @param { ValueType } high - indicates the maximum value. + * @returns { RdbPredicates } - the SQL statement with the specified {@link RdbPredicates}. + * @throws { BusinessError } 401 - if the parameter type is incorrect. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 9 + */ + notBetween(field: string, low: ValueType, high: ValueType): RdbPredicates; + + /** + * Restricts the value of the field to be greater than the specified value. + * + * @param { string } field - indicates the column name in the database table. + * @param { ValueType } value - indicates the value to match with the {@link RdbPredicates}. + * @returns { RdbPredicates } - the SQL query statement with the specified {@link RdbPredicates}. + * @throws { BusinessError } 401 - if the parameter type is incorrect. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 9 + */ + greaterThan(field: string, value: ValueType): RdbPredicates; + + /** + * Restricts the value of the field to be smaller than the specified value. + * + * @param { string } field - indicates the column name in the database table. + * @param { ValueType } value - indicates the value to match with the {@link RdbPredicates}. + * @returns { RdbPredicates } - the SQL query statement with the specified {@link RdbPredicates}. + * @throws { BusinessError } 401 - if the parameter type is incorrect. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 9 + */ + lessThan(field: string, value: ValueType): RdbPredicates; + + /** + * Restricts the value of the field to be greater than or equal to the specified value. + * + * @param { string } field - indicates the column name in the database table. + * @param { ValueType } value - indicates the value to match with the {@link RdbPredicates}. + * @returns { RdbPredicates } - the SQL query statement with the specified {@link RdbPredicates}. + * @throws { BusinessError } 401 - if the parameter type is incorrect. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 9 + */ + greaterThanOrEqualTo(field: string, value: ValueType): RdbPredicates; + + /** + * Restricts the value of the field to be smaller than or equal to the specified value. + * + * @param { string } field - indicates the column name in the database table. + * @param { ValueType } value - indicates the value to match with the {@link RdbPredicates}. + * @returns { RdbPredicates } - the SQL query statement with the specified {@link RdbPredicates}. + * @throws { BusinessError } 401 - if the parameter type is incorrect. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 9 + */ + lessThanOrEqualTo(field: string, value: ValueType): RdbPredicates; + + /** + * Restricts the ascending order of the return list. When there are several orders, + * the one close to the head has the highest priority. + * + * @param { string } field - indicates the column name for sorting the return list. + * @returns { RdbPredicates } - the SQL query statement with the specified {@link RdbPredicates}. + * @throws { BusinessError } 401 - if the parameter type is incorrect. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 9 + */ + orderByAsc(field: string): RdbPredicates; + + /** + * Restricts the descending order of the return list. When there are several orders, + * the one close to the head has the highest priority. + * + * @param { string } field - indicates the column name for sorting the return list. + * @returns { RdbPredicates } - the SQL query statement with the specified {@link RdbPredicates}. + * @throws { BusinessError } 401 - if the parameter type is incorrect. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 9 + */ + orderByDesc(field: string): RdbPredicates; + + /** + * Restricts each row of the query result to be unique. + * + * @returns { RdbPredicates } - the SQL query statement with the specified {@link RdbPredicates}. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 9 + */ + distinct(): RdbPredicates; + + /** + * Restricts the max number of return records. + * + * @param { number } value - indicates the max length of the return list. + * @returns { RdbPredicates } - the SQL query statement with the specified {@link RdbPredicates}. + * @throws { BusinessError } 401 - if the parameter type is incorrect. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 9 + */ + limitAs(value: number): RdbPredicates; + + /** + * Configure RdbPredicates to specify the start position of the returned result. + * Use this method together with limit(number). + * + * @param { number } rowOffset - indicates the start position of the returned result. The value is a positive integer. + * @returns { RdbPredicates } - the SQL query statement with the specified {@link RdbPredicates}. + * @throws { BusinessError } 401 - if the parameter type is incorrect. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 9 + */ + offsetAs(rowOffset: number): RdbPredicates; + + /** + * Configure RdbPredicates to group query results by specified columns. + * + * @param { Array } fields - indicates the specified columns by which query results are grouped. + * @returns { RdbPredicates } - the SQL query statement with the specified {@link RdbPredicates}. + * @throws { BusinessError } 401 - if the parameter type is incorrect. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 9 + */ + groupBy(fields: Array): RdbPredicates; + + /** + * Configure RdbPredicates to specify the index column. + * Before using this method, you need to create an index column. + * + * @param { string } field - indicates the name of the index column. + * @returns { RdbPredicates } - the SQL statement with the specified {@link RdbPredicates}. + * @throws { BusinessError } 401 - if the parameter type is incorrect. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 9 + */ + indexedBy(field: string): RdbPredicates; + + /** + * Configure RdbPredicates to match the specified field whose data type is ValueType array and values + * are within a given range. + * + * @param { string } field - indicates the column name in the database table. + * @param { Array } value - indicates the values to match with {@link RdbPredicates}. + * @returns { RdbPredicates } - the SQL statement with the specified {@link RdbPredicates}. + * @throws { BusinessError } 401 - if the parameter type is incorrect. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 9 + */ + in(field: string, value: Array): RdbPredicates; + + /** + * Configure RdbPredicates to match the specified field whose data type is ValueType array and values + * are out of a given range. + * + * @param { string } field - indicates the column name in the database table. + * @param { Array } value - indicates the values to match with {@link RdbPredicates}. + * @returns { RdbPredicates } - the SQL statement with the specified {@link RdbPredicates}. + * @throws { BusinessError } 401 - if the parameter type is incorrect. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 9 + */ + notIn(field: string, value: Array): RdbPredicates; + } + + /** + * Provides methods for accessing a database result set generated by querying the database. + * + * @interface ResultSet + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 9 + */ + interface ResultSet { + /** + * Obtains the names of all columns in a result set. + * The column names are returned as a string array, in which the strings are in the same order + * as the columns in the result set. + * + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 9 + */ + columnNames: Array; + + /** + * Obtains the number of columns in the result set. + * The returned number is equal to the length of the string array returned by the + * columnNames method. + * + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 9 + */ + columnCount: number; + + /** + * Obtains the number of rows in the result set. + * + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 9 + */ + rowCount: number; + + /** + * Obtains the current index of the result set. + * The result set index starts from 0. + * + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 9 + */ + rowIndex: number; + + /** + * Checks whether the cursor is positioned at the first row. + * + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 9 + */ + isAtFirstRow: boolean; + + /** + * Checks whether the cursor is positioned at the last row. + * + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 9 + */ + isAtLastRow: boolean; + + /** + * Checks whether the cursor is positioned after the last row. + * + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 9 + */ + isEnded: boolean; + + /** + * Checks whether the cursor is positioned before the first row. + * + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 9 + */ + isStarted: boolean; + + /** + * Checks whether the current result set is closed. + * If the result set is closed by calling the close method, true will be returned. + * + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 9 + */ + isClosed: boolean; + + /** + * Obtains the column index based on the specified column name. + * The column name is passed as an input parameter. + * + * @param { string } columnName - indicates the name of the specified column in the result set. + * @returns { number } the index of the specified column. + * @throws { BusinessError } 14800013 - the column value is null or the column type is incompatible. + * @throws { BusinessError } 401 - the parameter check failed. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 9 + */ + getColumnIndex(columnName: string): number; + + /** + * Obtains the column name based on the specified column index. + * The column index is passed as an input parameter. + * + * @param { number } columnIndex - indicates the index of the specified column in the result set. + * @returns { string } the name of the specified column. + * @throws { BusinessError } 14800013 - the column value is null or the column type is incompatible. + * @throws { BusinessError } 401 - parameter error. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 9 + */ + getColumnName(columnIndex: number): string; + + /** + * Go to the specified row of the result set forwards or backwards by an offset relative to its current position. + * A positive offset indicates moving backwards, and a negative offset indicates moving forwards. + * + * @param { number } offset - indicates the offset relative to the current position. + * @returns { boolean } true if the result set is moved successfully and does not go beyond the range; + * returns false otherwise. + * @throws { BusinessError } 14800012 - the result set is empty or the specified location is invalid. + * @throws { BusinessError } 401 - parameter error. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 9 + */ + goTo(offset: number): boolean; + + /** + * Go to the specified row of the result set. + * + * @param { number } position - indicates the index of the specified row, which starts from 0. + * @returns { boolean } true if the result set is moved successfully; returns false otherwise. + * @throws { BusinessError } 14800012 - the result set is empty or the specified location is invalid. + * @throws { BusinessError } 401 - parameter error. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 9 + */ + goToRow(position: number): boolean; + + /** + * Go to the first row of the result set. + * + * @returns { boolean } true if the result set is moved successfully; + * returns false otherwise, for example, if the result set is empty. + * @throws { BusinessError } 14800012 - the result set is empty or the specified location is invalid. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 9 + */ + goToFirstRow(): boolean; + + /** + * Go to the last row of the result set. + * + * @returns { boolean } true if the result set is moved successfully; + * returns false otherwise, for example, if the result set is empty. + * @throws { BusinessError } 14800012 - the result set is empty or the specified location is invalid. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 9 + */ + goToLastRow(): boolean; + + /** + * Go to the next row of the result set. + * + * @returns { boolean } true if the result set is moved successfully; + * returns false otherwise, for example, if the result set is already in the last row. + * @throws { BusinessError } 14800012 - the result set is empty or the specified location is invalid. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 9 + */ + goToNextRow(): boolean; + + /** + * Go to the previous row of the result set. + * + * @returns { boolean } true if the result set is moved successfully; + * returns false otherwise, for example, if the result set is already in the first row. + * @throws { BusinessError } 14800012 - the result set is empty or the specified location is invalid. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 9 + */ + goToPreviousRow(): boolean; + + /** + * Obtains the value of the specified column in the current row as a byte array. + * The implementation class determines whether to throw an exception if the value of the specified column + * in the current row is null or the specified column is not of the Blob type. + * + * @param { number } columnIndex - indicates the specified column index, which starts from 0. + * @returns { Uint8Array } the value of the specified column as a byte array. + * @throws { BusinessError } 14800013 - the column value is null or the column type is incompatible. + * @throws { BusinessError } 401 - the parameter check failed. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 9 + */ + getBlob(columnIndex: number): Uint8Array; + + /** + * Obtains the value of the specified column in the current row as string. + * The implementation class determines whether to throw an exception if the value of the specified column + * in the current row is null or the specified column is not of the string type. + * + * @param { number } columnIndex - indicates the specified column index, which starts from 0. + * @returns { string } the value of the specified column as a string. + * @throws { BusinessError } 14800013 - the column value is null or the column type is incompatible. + * @throws { BusinessError } 401 - the parameter check failed. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 9 + */ + getString(columnIndex: number): string; + + /** + * Obtains the value of the specified column in the current row as long. + * The implementation class determines whether to throw an exception if the value of the specified column + * in the current row is null, the specified column is not of the integer type. + * + * @param { number } columnIndex - indicates the specified column index, which starts from 0. + * @returns { number } the value of the specified column as a long. + * @throws { BusinessError } 14800013 - the column value is null or the column type is incompatible. + * @throws { BusinessError } 401 - the parameter check failed. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 9 + */ + getLong(columnIndex: number): number; + + /** + * Obtains the value of the specified column in the current row as double. + * The implementation class determines whether to throw an exception if the value of the specified column + * in the current row is null, the specified column is not of the double type. + * + * @param { number } columnIndex - indicates the specified column index, which starts from 0. + * @returns { number } the value of the specified column as a double. + * @throws { BusinessError } 14800013 - the column value is null or the column type is incompatible. + * @throws { BusinessError } 401 - the parameter check failed. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 9 + */ + getDouble(columnIndex: number): number; + + /** + * Obtains the modify time of current row. + * + * @returns { string } the modify time of current row. if it is not the cloud table, the time will be empty. + * @throws { BusinessError } 14800013 - the column value is null or the column type is incompatible. + * @throws { BusinessError } 401 - the parameter check failed. + * @syscap SystemCapability.DistributedDataManager.CloudSync.Client + * @since 10 + */ + getModifyTime(): string; + + /** + * Checks whether the value of the specified column in the current row is null. + * + * @param { number } columnIndex - indicates the specified column index, which starts from 0. + * @returns { boolean } true if the value of the specified column in the current row is null; + * returns false otherwise. + * @throws { BusinessError } 14800013 - the column value is null or the column type is incompatible. + * @throws { BusinessError } 401 - parameter error. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 9 + */ + isColumnNull(columnIndex: number): boolean; + + /** + * Closes the result set. + * Calling this method on the result set will release all of its resources and makes it ineffective. + * + * @throws { BusinessError } 14800012 - the result set is empty or the specified location is invalid. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 9 + */ + close(): void; + } +} + +export default relationalStore; diff --git a/relational_store/interfaces/inner_api/js/data/rdb/resultSet.d.ts b/relational_store/interfaces/inner_api/js/data/rdb/resultSet.d.ts new file mode 100644 index 00000000..351e3abf --- /dev/null +++ b/relational_store/interfaces/inner_api/js/data/rdb/resultSet.d.ts @@ -0,0 +1,303 @@ +/* + * 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. + */ + +import { AsyncCallback } from '../../@ohos.base'; + +/** + * Provides methods for accessing a database result set generated by querying the database. + * + * @interface ResultSet + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 7 + * @deprecated since 9 + * @useinstead ohos.data.relationalStore.ResultSet + */ +export interface ResultSet { + /** + * Obtains the names of all columns in a result set. + * The column names are returned as a string array, in which the strings are in the same order + * as the columns in the result set. + * + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 7 + * @deprecated since 9 + * @useinstead ohos.data.relationalStore.ResultSet.columnNames + */ + columnNames: Array; + + /** + * Obtains the number of columns in the result set. + * The returned number is equal to the length of the string array returned by the + * columnCount method. + * + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 7 + * @deprecated since 9 + * @useinstead ohos.data.relationalStore.ResultSet.columnCount + */ + columnCount: number; + + /** + * Obtains the number of rows in the result set. + * + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 7 + * @deprecated since 9 + * @useinstead ohos.data.relationalStore.ResultSet.rowCount + */ + rowCount: number; + + /** + * Obtains the current index of the result set. + * The result set index starts from 0. + * + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 7 + * @deprecated since 9 + * @useinstead ohos.data.relationalStore.ResultSet.rowIndex + */ + rowIndex: number; + + /** + * Checks whether the result set is positioned at the first row. + * + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 7 + * @deprecated since 9 + * @useinstead ohos.data.relationalStore.ResultSet.isAtFirstRow + */ + isAtFirstRow: boolean; + + /** + * Checks whether the result set is positioned at the last row. + * + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 7 + * @deprecated since 9 + * @useinstead ohos.data.relationalStore.ResultSet.isAtLastRow + */ + isAtLastRow: boolean; + + /** + * Checks whether the result set is positioned after the last row. + * + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 7 + * @deprecated since 9 + * @useinstead ohos.data.relationalStore.ResultSet.isEnded + */ + isEnded: boolean; + + /** + * returns whether the cursor is pointing to the position before the first + * row. + * + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 7 + * @deprecated since 9 + * @useinstead ohos.data.relationalStore.ResultSet.isStarted + */ + isStarted: boolean; + + /** + * Checks whether the current result set is closed. + * If the result set is closed by calling the close method, true will be returned. + * + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 7 + * @deprecated since 9 + * @useinstead ohos.data.relationalStore.ResultSet.isClosed + */ + isClosed: boolean; + + /** + * Obtains the column index based on the specified column name. + * The column name is passed as an input parameter. + * + * @param { string } columnName - Indicates the name of the specified column in the result set. + * @returns { number } return the index of the specified column. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 7 + * @deprecated since 9 + * @useinstead ohos.data.relationalStore.ResultSet.getColumnIndex + */ + getColumnIndex(columnName: string): number; + + /** + * Obtains the column name based on the specified column index. + * The column index is passed as an input parameter. + * + * @param { number } columnIndex - Indicates the index of the specified column in the result set. + * @returns { string } returns the name of the specified column. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 7 + * @deprecated since 9 + * @useinstead ohos.data.relationalStore.ResultSet.getColumnName + */ + getColumnName(columnIndex: number): string; + + /** + * Go to the specified row of the result set forwards or backwards by an offset relative to its current position. + * A positive offset indicates moving backwards, and a negative offset indicates moving forwards. + * + * @param { number } offset - Indicates the offset relative to the current position. + * @returns { boolean } returns true if the result set is moved successfully and does not go beyond the range; + * returns false otherwise. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 7 + * @deprecated since 9 + * @useinstead ohos.data.relationalStore.ResultSet.goTo + */ + goTo(offset: number): boolean; + + /** + * Go to the specified row of the result set. + * + * @param { number } position - Indicates the index of the specified row, which starts from 0. + * @returns { boolean } returns true if the result set is moved successfully; returns false otherwise. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 7 + * @deprecated since 9 + * @useinstead ohos.data.relationalStore.ResultSet.goToRow + */ + goToRow(position: number): boolean; + + /** + * Go to the first row of the result set. + * + * @returns { boolean } returns true if the result set is moved successfully; + * returns false otherwise, for example, if the result set is empty. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 7 + * @deprecated since 9 + * @useinstead ohos.data.relationalStore.ResultSet.goToFirstRow + */ + goToFirstRow(): boolean; + + /** + * Go to the last row of the result set. + * + * @returns { boolean } returns true if the result set is moved successfully; + * returns false otherwise, for example, if the result set is empty. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 7 + * @deprecated since 9 + * @useinstead ohos.data.relationalStore.ResultSet.goToLastRow + */ + goToLastRow(): boolean; + + /** + * Go to the next row of the result set. + * + * @returns { boolean } returns true if the result set is moved successfully; + * returns false otherwise, for example, if the result set is already in the last row. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 7 + * @deprecated since 9 + * @useinstead ohos.data.relationalStore.ResultSet.goToNextRow + */ + goToNextRow(): boolean; + + /** + * Go to the previous row of the result set. + * + * @returns { boolean } returns true if the result set is moved successfully; + * returns false otherwise, for example, if the result set is already in the first row. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 7 + * @deprecated since 9 + * @useinstead ohos.data.relationalStore.ResultSet.goToPreviousRow + */ + goToPreviousRow(): boolean; + + /** + * Obtains the value of the specified column in the current row as a byte array. + * The implementation class determines whether to throw an exception if the value of the specified column + * in the current row is null or the specified column is not of the Blob type. + * + * @param { number } columnIndex - Indicates the specified column index, which starts from 0. + * @returns { Uint8Array } returns the value of the specified column as a byte array. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 7 + * @deprecated since 9 + * @useinstead ohos.data.relationalStore.ResultSet.getBlob + */ + getBlob(columnIndex: number): Uint8Array; + + /** + * Obtains the value of the specified column in the current row as string. + * The implementation class determines whether to throw an exception if the value of the specified column + * in the current row is null or the specified column is not of the string type. + * + * @param { number } columnIndex - Indicates the specified column index, which starts from 0. + * @returns { string } returns the value of the specified column as a string. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 7 + * @deprecated since 9 + * @useinstead ohos.data.relationalStore.ResultSet.getString + */ + getString(columnIndex: number): string; + + /** + * Obtains the value of the specified column in the current row as long. + * The implementation class determines whether to throw an exception if the value of the specified column + * in the current row is null, the specified column is not of the integer type. + * + * @param { number } columnIndex - Indicates the specified column index, which starts from 0. + * @returns { number } returns the value of the specified column as a long. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 7 + * @deprecated since 9 + * @useinstead ohos.data.relationalStore.ResultSet.getLong + */ + getLong(columnIndex: number): number; + + /** + * Obtains the value of the specified column in the current row as double. + * The implementation class determines whether to throw an exception if the value of the specified column + * in the current row is null, the specified column is not of the double type. + * + * @param { number } columnIndex - Indicates the specified column index, which starts from 0. + * @returns { number } returns the value of the specified column as a double. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 7 + * @deprecated since 9 + * @useinstead ohos.data.relationalStore.ResultSet.getDouble + */ + getDouble(columnIndex: number): number; + + /** + * Checks whether the value of the specified column in the current row is null. + * + * @param { number } columnIndex - Indicates the specified column index, which starts from 0. + * @returns { boolean } returns true if the value of the specified column in the current row is null; + * returns false otherwise. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 7 + * @deprecated since 9 + * @useinstead ohos.data.relationalStore.ResultSet.isColumnNull + */ + isColumnNull(columnIndex: number): boolean; + /** + * Closes the result set. + * Calling this method on the result set will release all of its resources and makes it ineffective. + * + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 7 + * @deprecated since 9 + * @useinstead ohos.data.relationalStore.ResultSet.close + */ + close(): void; +} -- Gitee From 963f85a3eb17a579ec48b20ee87a06d5897c33c0 Mon Sep 17 00:00:00 2001 From: Sven Wang Date: Sun, 23 Apr 2023 19:20:40 +0800 Subject: [PATCH 28/44] update Signed-off-by: Sven Wang --- relational_store/CMakeLists.txt | 4 ++-- .../js/napi/relationalstore/include/napi_result_set.h | 1 + .../js/napi/relationalstore/src/napi_result_set.cpp | 10 ++++++++++ .../frameworks/native/rdb/src/abs_result_set.cpp | 5 +++++ .../interfaces/inner_api/rdb/include/abs_result_set.h | 1 + .../inner_api/rdb/include/abs_shared_result_set.h | 1 + .../interfaces/inner_api/rdb/include/result_set.h | 1 + 7 files changed, 21 insertions(+), 2 deletions(-) diff --git a/relational_store/CMakeLists.txt b/relational_store/CMakeLists.txt index 1fa45508..0b5c49a9 100644 --- a/relational_store/CMakeLists.txt +++ b/relational_store/CMakeLists.txt @@ -20,12 +20,12 @@ aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/frameworks/native/rdb_data_shar aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/frameworks/native/rdb_device_manager_adapter/src relational_store_src) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/frameworks/js/napi/common/src relational_store_src) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/frameworks/js/napi/dataability/src relational_store_src) -aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/frameworks/js/napi/rdb/src relational_store_src) +aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/frameworks/js/napi/relationalstore/src relational_store_src) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/frameworks/native/cloud_data/include) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/frameworks/native/rdb/include) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/frameworks/js/napi/common/include) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/frameworks/js/napi/dataability/include) -include_directories(${CMAKE_CURRENT_SOURCE_DIR}/frameworks/js/napi/rdb/include) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/frameworks/js/napi/relationalstore/include) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/interfaces/inner_api/appdatafwk/include) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/interfaces/inner_api/cloud_data/include) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/interfaces/inner_api/dataability/include) diff --git a/relational_store/frameworks/js/napi/relationalstore/include/napi_result_set.h b/relational_store/frameworks/js/napi/relationalstore/include/napi_result_set.h index aa3b1d4f..f0118af1 100644 --- a/relational_store/frameworks/js/napi/relationalstore/include/napi_result_set.h +++ b/relational_store/frameworks/js/napi/relationalstore/include/napi_result_set.h @@ -68,6 +68,7 @@ private: static napi_value GetBlob(napi_env env, napi_callback_info info); static napi_value GetString(napi_env env, napi_callback_info info); static napi_value GetDouble(napi_env env, napi_callback_info info); + static napi_value GetModifyTime(napi_env env, napi_callback_info info); static napi_value IsColumnNull(napi_env env, napi_callback_info info); static napi_value GetRow(napi_env env, napi_callback_info info); static napi_value IsClosed(napi_env env, napi_callback_info info); diff --git a/relational_store/frameworks/js/napi/relationalstore/src/napi_result_set.cpp b/relational_store/frameworks/js/napi/relationalstore/src/napi_result_set.cpp index b2748d96..5183714e 100644 --- a/relational_store/frameworks/js/napi/relationalstore/src/napi_result_set.cpp +++ b/relational_store/frameworks/js/napi/relationalstore/src/napi_result_set.cpp @@ -113,6 +113,7 @@ napi_value ResultSetProxy::GetConstructor(napi_env env) DECLARE_NAPI_FUNCTION("getBlob", GetBlob), DECLARE_NAPI_FUNCTION("getString", GetString), DECLARE_NAPI_FUNCTION("getDouble", GetDouble), + DECLARE_NAPI_FUNCTION("getModifyTime", GetModifyTime), DECLARE_NAPI_FUNCTION("isColumnNull", IsColumnNull), DECLARE_NAPI_FUNCTION("getRow", GetRow), @@ -491,6 +492,15 @@ napi_value ResultSetProxy::GetDouble(napi_env env, napi_callback_info info) return JSUtils::Convert2JSValue(env, result); } +napi_value ResultSetProxy::GetModifyTime(napi_env env, napi_callback_info info) +{ + int version; + std::string modifyTime; + auto ret = GetInnerResultSet(env, info, version)->GetModifyTime(modifyTime); + RDB_NAPI_ASSERT_FROMV9(env, ret != E, std::make_shared(), version); + return JSUtils::Convert2JSValue(env, modifyTime); +} + napi_value ResultSetProxy::GetColumnIndex(napi_env env, napi_callback_info info) { std::string input; diff --git a/relational_store/frameworks/native/rdb/src/abs_result_set.cpp b/relational_store/frameworks/native/rdb/src/abs_result_set.cpp index 1840a7a3..1a76944a 100644 --- a/relational_store/frameworks/native/rdb/src/abs_result_set.cpp +++ b/relational_store/frameworks/native/rdb/src/abs_result_set.cpp @@ -354,5 +354,10 @@ int AbsResultSet::Close() isClosed = true; return E_OK; } + +int AbsResultSet::GetModifyTime(std::string &modifyTime) +{ + return E_NOT_SUPPORT; +} } // namespace NativeRdb } // namespace OHOS \ No newline at end of file diff --git a/relational_store/interfaces/inner_api/rdb/include/abs_result_set.h b/relational_store/interfaces/inner_api/rdb/include/abs_result_set.h index 9f0011fe..a3ce68d4 100644 --- a/relational_store/interfaces/inner_api/rdb/include/abs_result_set.h +++ b/relational_store/interfaces/inner_api/rdb/include/abs_result_set.h @@ -112,6 +112,7 @@ public: */ RDB_API_EXPORT int GetDouble(int columnIndex, double &value) override; + RDB_API_EXPORT int GetModifyTime(std::string &modifyTime) override; /** * @brief Checks whether the value of the specified column in the current row is null. * diff --git a/relational_store/interfaces/inner_api/rdb/include/abs_shared_result_set.h b/relational_store/interfaces/inner_api/rdb/include/abs_shared_result_set.h index c2a68ce7..316dca7b 100644 --- a/relational_store/interfaces/inner_api/rdb/include/abs_shared_result_set.h +++ b/relational_store/interfaces/inner_api/rdb/include/abs_shared_result_set.h @@ -112,6 +112,7 @@ public: */ RDB_API_EXPORT int GetDouble(int columnIndex, double &value) override; + /** * @brief Checks whether the value of the specified column in the current row is null. * diff --git a/relational_store/interfaces/inner_api/rdb/include/result_set.h b/relational_store/interfaces/inner_api/rdb/include/result_set.h index ff08b21f..49a8fc53 100644 --- a/relational_store/interfaces/inner_api/rdb/include/result_set.h +++ b/relational_store/interfaces/inner_api/rdb/include/result_set.h @@ -51,6 +51,7 @@ public: * @brief Gets the entire row of data for the current row from the result set. */ RDB_API_EXPORT virtual int GetRow(RowEntity &rowEntity) = 0; + RDB_API_EXPORT virtual int GetModifyTime(std::string &modifyTime) = 0; }; } // namespace NativeRdb -- Gitee From 6a1815904bcf49a94454942c8a29b4d7158568b4 Mon Sep 17 00:00:00 2001 From: Sven Wang Date: Sun, 23 Apr 2023 20:20:59 +0800 Subject: [PATCH 29/44] update Signed-off-by: Sven Wang --- .../js/napi/common/include/js_utils.h | 17 +++++----- .../js/napi/common/src/js_utils.cpp | 31 +++++++++++++++-- .../dataability/src/napi_predicates_utils.cpp | 2 +- .../js/napi/rdb/include/napi_rdb_js_utils.h | 2 ++ .../js/napi/rdb/src/napi_rdb_js_utils.cpp | 5 +++ .../include/napi_rdb_js_utils.h | 30 +++++++++++++++++ .../relationalstore/src/napi_rdb_js_utils.cpp | 31 +++++++++++++++++ .../relationalstore/src/napi_rdb_store.cpp | 33 +++---------------- .../src/napi_rdb_store_helper.cpp | 2 +- .../src/napi_rdb_store_observer.cpp | 2 +- .../relationalstore/src/napi_result_set.cpp | 6 ++-- .../native/rdb/include/iresult_set.h | 4 +-- .../inner_api/rdb/include/result_set.h | 4 +-- 13 files changed, 120 insertions(+), 49 deletions(-) create mode 100644 relational_store/frameworks/js/napi/relationalstore/include/napi_rdb_js_utils.h create mode 100644 relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_js_utils.cpp diff --git a/relational_store/frameworks/js/napi/common/include/js_utils.h b/relational_store/frameworks/js/napi/common/include/js_utils.h index 3b04d6ab..df9e9b60 100644 --- a/relational_store/frameworks/js/napi/common/include/js_utils.h +++ b/relational_store/frameworks/js/napi/common/include/js_utils.h @@ -40,9 +40,11 @@ constexpr int32_t SYNC_RESULT_ELEMNT_NUM = 2; std::string Convert2String(napi_env env, napi_value jsStr, bool useDefaultBufSize = true); int32_t Convert2Value(napi_env env, napi_value jsBool, bool &output); +int32_t Convert2Value(napi_env env, napi_value jsNum, int64_t &output); int32_t Convert2Value(napi_env env, napi_value jsNum, double &output); int32_t Convert2Value(napi_env env, napi_value jsStr, std::string &output); int32_t Convert2Value(napi_env env, napi_value jsValue, std::vector &output); +int32_t Convert2Value(napi_env env, napi_value jsValue, std::monostate &value); std::vector Convert2StrVector(napi_env env, napi_value value); std::vector Convert2U8Vector(napi_env env, napi_value jsValue); std::string ConvertAny2String(napi_env env, napi_value jsValue); @@ -52,7 +54,7 @@ int32_t Convert2Value(napi_env env, napi_value jsValue, T &output); template int32_t Convert2Value(napi_env env, napi_value jsValue, std::vector &value); template -int32_t Convert2Value(napi_env env, napi_value jsValue, const std::variant<_Types...> &value); +int32_t Convert2Value(napi_env env, napi_value jsValue, std::variant<_Types...> &value); template napi_value Convert2JSValue(napi_env env, const std::variant<_Types...> &value); @@ -119,23 +121,22 @@ template int32_t JSUtils::Convert2Value(napi_env env, napi_value jsValue, std::vector &value) { uint32_t arrLen = 0; - napi_get_array_length(env, value, &arrLen); + napi_get_array_length(env, jsValue, &arrLen); if (arrLen == 0) { return napi_ok; } - std::vector result; for (size_t i = 0; i < arrLen; ++i) { napi_value element; - napi_get_element(env, value, i, &element); - T value; - Convert2Value(env, element, value); - result.push_back(std::move(value)); + napi_get_element(env, jsValue, i, &element); + T item; + Convert2Value(env, element, item); + value.push_back(std::move(item)); } return napi_ok; } template -int32_t JSUtils::Convert2Value(napi_env env, napi_value jsValue, const std::variant<_Types...> &value) +int32_t JSUtils::Convert2Value(napi_env env, napi_value jsValue, std::variant<_Types...> &value) { return GetCPPValue(env, jsValue, value); } diff --git a/relational_store/frameworks/js/napi/common/src/js_utils.cpp b/relational_store/frameworks/js/napi/common/src/js_utils.cpp index a86b3838..3cc72bfa 100644 --- a/relational_store/frameworks/js/napi/common/src/js_utils.cpp +++ b/relational_store/frameworks/js/napi/common/src/js_utils.cpp @@ -79,6 +79,23 @@ int32_t JSUtils::Convert2Value(napi_env env, napi_value jsValue, std::vectorGetIndex(), absPredicates->GetGroup(), absPredicates->GetOrder(), absPredicates->GetLimit(), absPredicates->GetOffset()); - return RdbJsKit::RdbPredicatesProxy::NewInstance(env, predicates); + return RelationalStoreJsKit::RdbPredicatesProxy::NewInstance(env, predicates); } napi_value InitPredicatesUtils(napi_env env, napi_value exports) diff --git a/relational_store/frameworks/js/napi/rdb/include/napi_rdb_js_utils.h b/relational_store/frameworks/js/napi/rdb/include/napi_rdb_js_utils.h index def10f22..22c5dcc7 100644 --- a/relational_store/frameworks/js/napi/rdb/include/napi_rdb_js_utils.h +++ b/relational_store/frameworks/js/napi/rdb/include/napi_rdb_js_utils.h @@ -22,6 +22,8 @@ namespace OHOS::AppDataMgrJsKit { namespace JSUtils { using Asset = OHOS::NativeRdb::AssetValue; template<> +int32_t Convert2Value(napi_env env, napi_value input, Asset &output); +template<> napi_value Convert2JSValue(napi_env env, const Asset &value); }; // namespace JSUtils } // namespace OHOS::AppDataMgrJsKit diff --git a/relational_store/frameworks/js/napi/rdb/src/napi_rdb_js_utils.cpp b/relational_store/frameworks/js/napi/rdb/src/napi_rdb_js_utils.cpp index 90bde88d..e6415eae 100644 --- a/relational_store/frameworks/js/napi/rdb/src/napi_rdb_js_utils.cpp +++ b/relational_store/frameworks/js/napi/rdb/src/napi_rdb_js_utils.cpp @@ -17,6 +17,11 @@ namespace OHOS::AppDataMgrJsKit { namespace JSUtils { template<> +int32_t Convert2Value(napi_env env, napi_value input, Asset &output) +{ + return nullptr; +} +template<> napi_value Convert2JSValue(napi_env env, const Asset &value) { return nullptr; diff --git a/relational_store/frameworks/js/napi/relationalstore/include/napi_rdb_js_utils.h b/relational_store/frameworks/js/napi/relationalstore/include/napi_rdb_js_utils.h new file mode 100644 index 00000000..22c5dcc7 --- /dev/null +++ b/relational_store/frameworks/js/napi/relationalstore/include/napi_rdb_js_utils.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef RDB_JSKIT_NAPI_RDB_JS_UTILS_H +#define RDB_JSKIT_NAPI_RDB_JS_UTILS_H +#include "asset_value.h" +#include "value_object.h" +#include "js_utils.h" +namespace OHOS::AppDataMgrJsKit { +namespace JSUtils { +using Asset = OHOS::NativeRdb::AssetValue; +template<> +int32_t Convert2Value(napi_env env, napi_value input, Asset &output); +template<> +napi_value Convert2JSValue(napi_env env, const Asset &value); +}; // namespace JSUtils +} // namespace OHOS::AppDataMgrJsKit +#endif // RDB_JSKIT_NAPI_RDB_JS_UTILS_H diff --git a/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_js_utils.cpp b/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_js_utils.cpp new file mode 100644 index 00000000..db0c0f07 --- /dev/null +++ b/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_js_utils.cpp @@ -0,0 +1,31 @@ +/* + * 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. + */ + +#include "napi_rdb_js_utils.h" +namespace OHOS::AppDataMgrJsKit { +namespace JSUtils { +template<> +int32_t Convert2Value(napi_env env, napi_value jsValue, Asset &output) +{ + return OK; +} +template<> +napi_value Convert2JSValue(napi_env env, const Asset &value) +{ + return nullptr; +} + +}; // namespace JSUtils +} // namespace OHOS::AppDataMgrJsKit \ No newline at end of file diff --git a/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_store.cpp b/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_store.cpp index d9aed0e3..aa2cce2e 100644 --- a/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_store.cpp +++ b/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_store.cpp @@ -704,35 +704,10 @@ int ParseBindArgs(const napi_env &env, const napi_value &arg, std::shared_ptr(std::to_string(i), "a correct boolean")); - context->bindArgs.push_back(ValueObject(value)); - } break; - case napi_number: { - double value; - int32_t ret = JSUtils::Convert2Double(env, element, value); - CHECK_RETURN_SET(ret == OK, std::make_shared(std::to_string(i), "a correct number")); - context->bindArgs.push_back(ValueObject(value)); - } break; - case napi_null: { - context->bindArgs.push_back(ValueObject()); - } break; - case napi_string: { - context->bindArgs.push_back(ValueObject(JSUtils::Convert2String(env, element, false))); - } break; - case napi_object: { - std::vector value; - int32_t ret = JSUtils::Convert2U8Vector(env, element, value); - CHECK_RETURN_SET(ret == OK, std::make_shared(std::to_string(i), "Uint8Array")); - context->bindArgs.push_back(ValueObject(value)); - } break; - default: { - CHECK_RETURN_SET(false, std::make_shared(std::to_string(i), "a valid ValueType")); - } break; - } + ValueObject valueObject; + int32_t ret = JSUtils::Convert2Value(env, element, valueObject.value); + CHECK_RETURN_SET(ret == OK, std::make_shared(std::to_string(i), "ValueObject")); + context->bindArgs.push_back(std::move(valueObject)); } return OK; } diff --git a/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_store_helper.cpp b/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_store_helper.cpp index 03a4392d..687057e4 100644 --- a/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_store_helper.cpp +++ b/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_store_helper.cpp @@ -77,7 +77,7 @@ int ParseIsEncrypt(const napi_env &env, const napi_value &object, std::shared_pt napi_status status = napi_get_named_property(env, object, "encrypt", &value); if (status == napi_ok && value != nullptr) { bool isEncrypt = false; - JSUtils::Convert2Bool(env, value, isEncrypt); + JSUtils::Convert2Value(env, value, isEncrypt); context->config.SetEncryptStatus(isEncrypt); } return OK; diff --git a/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_store_observer.cpp b/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_store_observer.cpp index 0257e361..a6b20cf6 100644 --- a/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_store_observer.cpp +++ b/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_store_observer.cpp @@ -18,7 +18,7 @@ #include "js_logger.h" #include "js_utils.h" -using OHOS::AppDataMgrJsKit::JSUtils; +using namespace OHOS::AppDataMgrJsKit; using OHOS::AppDataMgrJsKit::PREFIX_LABEL; namespace OHOS::RelationalStoreJsKit { diff --git a/relational_store/frameworks/js/napi/relationalstore/src/napi_result_set.cpp b/relational_store/frameworks/js/napi/relationalstore/src/napi_result_set.cpp index 5183714e..cccb3d9f 100644 --- a/relational_store/frameworks/js/napi/relationalstore/src/napi_result_set.cpp +++ b/relational_store/frameworks/js/napi/relationalstore/src/napi_result_set.cpp @@ -494,10 +494,10 @@ napi_value ResultSetProxy::GetDouble(napi_env env, napi_callback_info info) napi_value ResultSetProxy::GetModifyTime(napi_env env, napi_callback_info info) { - int version; + auto resultSet = GetInnerResultSet(env, info); + CHECK_RETURN_NULL(resultSet && resultSet->resultSet_); std::string modifyTime; - auto ret = GetInnerResultSet(env, info, version)->GetModifyTime(modifyTime); - RDB_NAPI_ASSERT_FROMV9(env, ret != E, std::make_shared(), version); + resultSet->resultSet_->GetModifyTime(modifyTime); return JSUtils::Convert2JSValue(env, modifyTime); } diff --git a/relational_store/frameworks/native/rdb/include/iresult_set.h b/relational_store/frameworks/native/rdb/include/iresult_set.h index 0206aa12..01da83b1 100644 --- a/relational_store/frameworks/native/rdb/include/iresult_set.h +++ b/relational_store/frameworks/native/rdb/include/iresult_set.h @@ -16,11 +16,11 @@ #ifndef NATIVE_RDB_IRESULT_SET_H #define NATIVE_RDB_IRESULT_SET_H -#include "result_set.h" +#include "abs_result_set.h" #include "iremote_broker.h" namespace OHOS::NativeRdb { -class IResultSet : public ResultSet, public IRemoteBroker { +class IResultSet : public AbsResultSet, public IRemoteBroker { public: virtual ~IResultSet() = default; DECLARE_INTERFACE_DESCRIPTOR(u"OHOS::NativeRdb.IResultSet"); diff --git a/relational_store/interfaces/inner_api/rdb/include/result_set.h b/relational_store/interfaces/inner_api/rdb/include/result_set.h index 49a8fc53..0b13073a 100644 --- a/relational_store/interfaces/inner_api/rdb/include/result_set.h +++ b/relational_store/interfaces/inner_api/rdb/include/result_set.h @@ -50,8 +50,8 @@ public: /** * @brief Gets the entire row of data for the current row from the result set. */ - RDB_API_EXPORT virtual int GetRow(RowEntity &rowEntity) = 0; - RDB_API_EXPORT virtual int GetModifyTime(std::string &modifyTime) = 0; + virtual int GetRow(RowEntity &rowEntity) = 0; + virtual int GetModifyTime(std::string &modifyTime) = 0; }; } // namespace NativeRdb -- Gitee From c2b541bd880081c8d82ed90ed595e74268940ee3 Mon Sep 17 00:00:00 2001 From: Sven Wang Date: Sun, 23 Apr 2023 20:39:26 +0800 Subject: [PATCH 30/44] update Signed-off-by: Sven Wang --- .../relationalstore/include/napi_rdb_store.h | 1 + .../src/napi_rdb_const_properties.cpp | 28 +++++++++++++++++++ .../relationalstore/src/napi_rdb_store.cpp | 6 ++++ .../inner_api/rdb/include/rdb_types.h | 4 +++ 4 files changed, 39 insertions(+) diff --git a/relational_store/frameworks/js/napi/relationalstore/include/napi_rdb_store.h b/relational_store/frameworks/js/napi/relationalstore/include/napi_rdb_store.h index 7be65cf4..5d10f762 100644 --- a/relational_store/frameworks/js/napi/relationalstore/include/napi_rdb_store.h +++ b/relational_store/frameworks/js/napi/relationalstore/include/napi_rdb_store.h @@ -69,6 +69,7 @@ private: static napi_value SetDistributedTables(napi_env env, napi_callback_info info); static napi_value ObtainDistributedTableName(napi_env env, napi_callback_info info); static napi_value Sync(napi_env env, napi_callback_info info); + static napi_value CloudSync(napi_env env, napi_callback_info info); static napi_value OnEvent(napi_env env, napi_callback_info info); static napi_value OffEvent(napi_env env, napi_callback_info info); diff --git a/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_const_properties.cpp b/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_const_properties.cpp index 44c80ca2..06629ba7 100644 --- a/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_const_properties.cpp +++ b/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_const_properties.cpp @@ -54,6 +54,9 @@ static napi_value ExportSyncMode(napi_env env) SET_NAPI_PROPERTY(syncMode, "SYNC_MODE_PUSH", SyncMode::PUSH); SET_NAPI_PROPERTY(syncMode, "SYNC_MODE_PULL", SyncMode::PULL); + SET_NAPI_PROPERTY(syncMode, "SYNC_MODE_TIME_FIRST", SyncMode::TIME_FIRST); + SET_NAPI_PROPERTY(syncMode, "SYNC_MODE_NATIVE_FIRST", SyncMode::NATIVE_FIRST); + SET_NAPI_PROPERTY(syncMode, "SYNC_MODE_CLOUD_FIRST", SyncMode::CLOUD_FIRST); napi_object_freeze(env, syncMode); return syncMode; } @@ -64,6 +67,7 @@ static napi_value ExportSubscribeType(napi_env env) napi_create_object(env, &subscribeType); SET_NAPI_PROPERTY(subscribeType, "SUBSCRIBE_TYPE_REMOTE", SubscribeMode::REMOTE); + SET_NAPI_PROPERTY(subscribeType, "SUBSCRIBE_TYPE_CLOUD", SubscribeMode::REMOTE); napi_object_freeze(env, subscribeType); return subscribeType; } @@ -81,6 +85,28 @@ static napi_value ExportSecurityLevel(napi_env env) return securityLevel; } #endif +static napi_value ExportProgress(napi_env env) +{ + napi_value progress = nullptr; + napi_create_object(env, &progress); + + SET_NAPI_PROPERTY(progress, "SYNC_BEGIN", 0); + SET_NAPI_PROPERTY(progress, "SYNC_IN_PROGRESS", 1); + SET_NAPI_PROPERTY(progress, "SYNC_FINISH", 2); + napi_object_freeze(env, progress); + return progress; +} + +static napi_value ExportDistributedType(napi_env env) +{ + napi_value distributedType = nullptr; + napi_create_object(env, &distributedType); + + SET_NAPI_PROPERTY(distributedType, "DISTRIBUTED_DEVICE", 0); + SET_NAPI_PROPERTY(distributedType, "DISTRIBUTED_CLOUD", 1); + napi_object_freeze(env, distributedType); + return distributedType; +} static napi_value ExportConflictResolution(napi_env env) { @@ -107,6 +133,8 @@ napi_status InitConstProperties(napi_env env, napi_value exports) DECLARE_NAPI_PROPERTY("SubscribeType", ExportSubscribeType(env)), DECLARE_NAPI_PROPERTY("SecurityLevel", ExportSecurityLevel(env)), #endif + DECLARE_NAPI_PROPERTY("Progress", ExportProgress(env)), + DECLARE_NAPI_PROPERTY("DistributedType", ExportDistributedType(env)), }; size_t count = sizeof(properties) / sizeof(properties[0]); diff --git a/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_store.cpp b/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_store.cpp index aa2cce2e..885be3c7 100644 --- a/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_store.cpp +++ b/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_store.cpp @@ -169,6 +169,7 @@ void RdbStoreProxy::Init(napi_env env, napi_value exports) DECLARE_NAPI_FUNCTION("setDistributedTables", SetDistributedTables), DECLARE_NAPI_FUNCTION("obtainDistributedTableName", ObtainDistributedTableName), DECLARE_NAPI_FUNCTION("sync", Sync), + DECLARE_NAPI_FUNCTION("cloudSync", CloudSync), DECLARE_NAPI_FUNCTION("on", OnEvent), DECLARE_NAPI_FUNCTION("off", OffEvent), #endif @@ -1113,6 +1114,11 @@ napi_value RdbStoreProxy::Sync(napi_env env, napi_callback_info info) return AsyncCall::Call(env, context); } +napi_value RdbStoreProxy::CloudSync(napi_env env, napi_callback_info info) +{ + return nullptr; +} + int RdbStoreProxy::OnDataChangeEvent(napi_env env, size_t argc, napi_value *argv) { napi_valuetype type; diff --git a/relational_store/interfaces/inner_api/rdb/include/rdb_types.h b/relational_store/interfaces/inner_api/rdb/include/rdb_types.h index 14934409..4e3d2c1e 100644 --- a/relational_store/interfaces/inner_api/rdb/include/rdb_types.h +++ b/relational_store/interfaces/inner_api/rdb/include/rdb_types.h @@ -58,6 +58,9 @@ struct CloudParam { enum SyncMode { PUSH, PULL, + TIME_FIRST, + NATIVE_FIRST, + CLOUD_FIRST, }; struct SyncOption { @@ -103,6 +106,7 @@ struct RdbPredicates { enum SubscribeMode { REMOTE, + CLOUD, SUBSCRIBE_MODE_MAX }; -- Gitee From 31fcd8c7c45248dda0daf6d6b59588863114b3a1 Mon Sep 17 00:00:00 2001 From: htt1997 Date: Mon, 24 Apr 2023 15:08:24 +0800 Subject: [PATCH 31/44] update Signed-off-by: htt1997 --- data_object/interfaces/innerkits/BUILD.gn | 2 +- data_object/interfaces/jskits/BUILD.gn | 2 +- .../native/common/src/shared_block.cpp | 2 +- .../native/consumer/src/datashare_helper.cpp | 331 +- .../native/provider/include/datashare_stub.h | 1 + .../native/provider/src/datashare_stub.cpp | 4 + .../src/mediadatashare_unit_test.cpp | 52 +- .../app/distributed_data.cfg | 3 +- .../distributeddataservice/framework/BUILD.gn | 6 + .../framework/cloud/cloud_event.cpp | 19 +- .../framework/cloud/cloud_server.cpp | 20 + .../framework/include/cloud/cloud_event.h | 18 +- .../framework/include/cloud/cloud_server.h | 9 +- .../distributeddataservice/service/BUILD.gn | 7 + .../service/cloud/cloud_service_impl.cpp | 6 +- .../data_share/data_share_service_stub.cpp | 1 - .../service/rdb/rdb_service_impl.cpp | 29 +- .../service/rdb/rdb_service_impl.h | 2 +- .../service/rdb/rdb_service_stub.cpp | 12 +- .../service/rdb/rdb_service_stub.h | 4 +- kv_store/frameworks/common/log_print.h | 10 +- mock/include/CMakeLists.txt | 2 +- .../runtime/include/js_runtime.h | 26 +- .../ability_runtime/runtime/include/runtime.h | 12 +- .../appexecfwk_base/include/ability_info.h | 9 +- .../appexecfwk_base/include/ability_info.h | 23 +- .../include/appexecfwk_errors.h | 154 +- .../include/application_info.h | 48 +- .../include/bundle_common_event.h | 36 +- .../appexecfwk_base/include/bundle_info.h | 28 +- .../bundlemgr/bundle_installer_interface.h | 1 + .../include/bundlemgr/bundle_mgr_interface.h | 43 +- .../bundlemgr/status_receiver_interface.h | 48 +- .../devicemanagersdk/include/device_manager.h | 426 +- .../include/device_manager_impl.h | 30 +- .../huks/libhukssdk/include/hks_log.h | 34 +- .../huks/libhukssdk/include/hks_template.h | 79 +- .../huks/libhukssdk/include/hks_type.h | 454 +- .../ipc/ipc_core/include/ipc_object_proxy.h | 14 +- .../ipc/ipc_core/include/ipc_object_stub.h | 17 +- .../ipc/ipc_core/include/ipc_skeleton.h | 6 + .../ipc/ipc_core/include/ipc_types.h | 8 +- .../ipc/ipc_core/include/iremote_broker.h | 40 +- .../ipc/ipc_core/include/iremote_object.h | 2 +- .../ipc/libdbinder/include/dbinder_service.h | 72 +- .../libdbinder/include/dbinder_service_stub.h | 10 +- mock/sqlite/include/sqlite3.h | 1314 +- mock/sqlite/include/sqlite3ext.h | 640 +- mock/sqlite/include/sqlite3sym.h | 38 +- mock/sqlite/src/shell.c | 31280 ++++++++-------- mock/sqlite/src/sqlite3.c | 6 +- mock/src/mock_device_manager.cpp | 47 +- mock/src/mock_huks.cpp | 545 +- mock/src/mock_ipc.cpp | 83 +- mock/src/mock_ipc_object_stub.cpp | 20 - mock/src/mock_js_runtime.cpp | 89 +- preferences/interfaces/inner_api/BUILD.gn | 2 +- relational_store/bundle.json | 11 + .../native/rdb/include/rdb_manager_impl.h | 3 +- .../native/rdb/include/rdb_service_proxy.h | 2 +- .../native/rdb/src/abs_rdb_predicates.cpp | 4 - .../frameworks/native/rdb/src/rdb_manager.cpp | 24 - .../native/rdb/src/rdb_manager_impl.cpp | 8 +- .../native/rdb/src/rdb_service_proxy.cpp | 8 +- .../native/rdb/src/rdb_store_config.cpp | 21 - .../native/rdb/src/rdb_store_impl.cpp | 50 +- .../interfaces/inner_api/cloud_data/BUILD.gn | 67 + .../cloud_data/include/cloud_manager.h | 3 +- .../cloud_data/include/cloud_service.h | 8 +- .../interfaces/inner_api/rdb/BUILD.gn | 2 - .../inner_api/rdb/include/rdb_service.h | 6 +- .../inner_api/rdb/include/rdb_store_config.h | 23 +- .../inner_api/rdb/include/rdb_types.h | 2 +- .../inner_api/rdb/include/values_bucket.h | 2 +- relational_store/relational_store.gni | 2 + test/include/CMakeLists.txt | 1 + 76 files changed, 18873 insertions(+), 17600 deletions(-) rename relational_store/frameworks/native/rdb/include/rdb_manager.h => mock/innerkits/bundle_framework/appexecfwk_base/include/bundle_common_event.h (38%) delete mode 100644 relational_store/frameworks/native/rdb/src/rdb_manager.cpp create mode 100644 relational_store/interfaces/inner_api/cloud_data/BUILD.gn diff --git a/data_object/interfaces/innerkits/BUILD.gn b/data_object/interfaces/innerkits/BUILD.gn index 2051c3ef..0869ce97 100644 --- a/data_object/interfaces/innerkits/BUILD.gn +++ b/data_object/interfaces/innerkits/BUILD.gn @@ -13,7 +13,7 @@ import("//build/ohos.gni") config("objectstore_config") { - visibility = [ "//foundation/distributeddatamgr/data_object:*" ] + visibility = [ ":*" ] cflags = [ "-DHILOG_ENABLE" ] diff --git a/data_object/interfaces/jskits/BUILD.gn b/data_object/interfaces/jskits/BUILD.gn index 52f503a4..d8d771bf 100644 --- a/data_object/interfaces/jskits/BUILD.gn +++ b/data_object/interfaces/jskits/BUILD.gn @@ -43,7 +43,7 @@ action("gen_distributed_data_object_abc") { } config("objectstore_config") { - visibility = [ "//foundation/distributeddatamgr/objectstore:*" ] + visibility = [ ":*" ] cflags = [ "-DHILOG_ENABLE" ] diff --git a/data_share/frameworks/native/common/src/shared_block.cpp b/data_share/frameworks/native/common/src/shared_block.cpp index bdb418ac..49380206 100644 --- a/data_share/frameworks/native/common/src/shared_block.cpp +++ b/data_share/frameworks/native/common/src/shared_block.cpp @@ -38,7 +38,7 @@ SharedBlock::~SharedBlock() if (ashmem_ != nullptr) { ashmem_->UnmapAshmem(); ashmem_->CloseAshmem(); - LOG_WARN("SharedBlock: close ashmem"); + LOG_DEBUG("SharedBlock: close ashmem"); } } diff --git a/data_share/frameworks/native/consumer/src/datashare_helper.cpp b/data_share/frameworks/native/consumer/src/datashare_helper.cpp index b254599c..829b1c36 100644 --- a/data_share/frameworks/native/consumer/src/datashare_helper.cpp +++ b/data_share/frameworks/native/consumer/src/datashare_helper.cpp @@ -1,17 +1,17 @@ /* -* 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. -*/ + * 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 "datashare_helper.h" @@ -42,10 +42,9 @@ private: std::shared_ptr dataShareObserver_; }; -DataShareHelper::DataShareHelper( - const sptr &token, const Uri &uri, std::shared_ptr dataShareConnection) +DataShareHelper::DataShareHelper(const sptr &token, const Uri &uri, + std::shared_ptr dataShareConnection) { - LOG_INFO("DataShareHelper::DataShareHelper start"); token_ = token; uri_ = uri; isDataShareService_ = (uri_.GetQuery().find("Proxy=true") != std::string::npos); @@ -54,11 +53,9 @@ DataShareHelper::DataShareHelper( DataShareHelper::DataShareHelper(const sptr &token, const Uri &uri) { - LOG_INFO("DataShareHelper::DataShareHelper start"); token_ = token; uri_ = uri; isDataShareService_ = (uri_.GetQuery().find("Proxy=true") != std::string::npos); - LOG_INFO("DataShareHelper::DataShareHelper end"); } DataShareHelper::~DataShareHelper() @@ -66,15 +63,15 @@ DataShareHelper::~DataShareHelper() } /** -* @brief You can use this method to specify the Uri of the data to operate and set the binding relationship -* between the ability using the Data template (data share for short) and the associated client process in -* a DataShareHelper instance. -* -* @param context Indicates the Context object on OHOS. -* @param strUri Indicates the database table or disk file to operate. -* -* @return Returns the created DataShareHelper instance. -*/ + * @brief You can use this method to specify the Uri of the data to operate and set the binding relationship + * between the ability using the Data template (data share for short) and the associated client process in + * a DataShareHelper instance. + * + * @param context Indicates the Context object on OHOS. + * @param strUri Indicates the database table or disk file to operate. + * + * @return Returns the created DataShareHelper instance. + */ std::shared_ptr DataShareHelper::Creator( const std::shared_ptr &context, const std::string &strUri) { @@ -87,15 +84,15 @@ std::shared_ptr DataShareHelper::Creator( } /** -* @brief You can use this method to specify the Uri of the data to operate and set the binding relationship -* between the ability using the Data template (data share for short) and the associated client process in -* a DataShareHelper instance. -* -* @param token Indicates the System token. -* @param strUri Indicates the database table or disk file to operate. -* -* @return Returns the created DataShareHelper instance. -*/ + * @brief You can use this method to specify the Uri of the data to operate and set the binding relationship + * between the ability using the Data template (data share for short) and the associated client process in + * a DataShareHelper instance. + * + * @param token Indicates the System token. + * @param strUri Indicates the database table or disk file to operate. + * + * @return Returns the created DataShareHelper instance. + */ std::shared_ptr DataShareHelper::Creator(const sptr &token, const std::string &strUri) { if (token == nullptr) { @@ -129,27 +126,27 @@ std::shared_ptr DataShareHelper::Creator(const sptr DataShareHelper::GetFileTypes(Uri &uri, const std::string &mimeTypeFilter) { std::vector matchedMIMEs; @@ -172,16 +169,16 @@ std::vector DataShareHelper::GetFileTypes(Uri &uri, const std::stri } /** -* @brief Opens a file in a specified remote path. -* -* @param uri Indicates the path of the file to open. -* @param mode Indicates the file open mode, which can be "r" for read-only access, "w" for write-only access -* (erasing whatever data is currently in the file), "wt" for write access that truncates any existing file, -* "wa" for write-only access to append to any existing data, "rw" for read and write access on any existing data, -* or "rwt" for read and write access that truncates any existing file. -* -* @return Returns the file descriptor. -*/ + * @brief Opens a file in a specified remote path. + * + * @param uri Indicates the path of the file to open. + * @param mode Indicates the file open mode, which can be "r" for read-only access, "w" for write-only access + * (erasing whatever data is currently in the file), "wt" for write access that truncates any existing file, + * "wa" for write-only access to append to any existing data, "rw" for read and write access on any existing data, + * or "rwt" for read and write access that truncates any existing file. + * + * @return Returns the file descriptor. + */ int DataShareHelper::OpenFile(Uri &uri, const std::string &mode) { int fd = INVALID_VALUE; @@ -204,17 +201,17 @@ int DataShareHelper::OpenFile(Uri &uri, const std::string &mode) } /** -* @brief This is like openFile, open a file that need to be able to return sub-sections of files,often assets -* inside of their .hap. -* -* @param uri Indicates the path of the file to open. -* @param mode Indicates the file open mode, which can be "r" for read-only access, "w" for write-only access -* (erasing whatever data is currently in the file), "wt" for write access that truncates any existing file, -* "wa" for write-only access to append to any existing data, "rw" for read and write access on any existing -* data, or "rwt" for read and write access that truncates any existing file. -* -* @return Returns the RawFileDescriptor object containing file descriptor. -*/ + * @brief This is like openFile, open a file that need to be able to return sub-sections of files,often assets + * inside of their .hap. + * + * @param uri Indicates the path of the file to open. + * @param mode Indicates the file open mode, which can be "r" for read-only access, "w" for write-only access + * (erasing whatever data is currently in the file), "wt" for write access that truncates any existing file, + * "wa" for write-only access to append to any existing data, "rw" for read and write access on any existing + * data, or "rwt" for read and write access that truncates any existing file. + * + * @return Returns the RawFileDescriptor object containing file descriptor. + */ int DataShareHelper::OpenRawFile(Uri &uri, const std::string &mode) { int fd = INVALID_VALUE; @@ -237,13 +234,13 @@ int DataShareHelper::OpenRawFile(Uri &uri, const std::string &mode) } /** -* @brief Inserts a single data record into the database. -* -* @param uri Indicates the path of the data to operate. -* @param value Indicates the data record to insert. If this parameter is null, a blank row will be inserted. -* -* @return Returns the index of the inserted data record. -*/ + * @brief Inserts a single data record into the database. + * + * @param uri Indicates the path of the data to operate. + * @param value Indicates the data record to insert. If this parameter is null, a blank row will be inserted. + * + * @return Returns the index of the inserted data record. + */ int DataShareHelper::Insert(Uri &uri, const DataShareValuesBucket &value) { int index = INVALID_VALUE; @@ -266,14 +263,14 @@ int DataShareHelper::Insert(Uri &uri, const DataShareValuesBucket &value) } /** -* @brief Updates data records in the database. -* -* @param uri Indicates the path of data to update. -* @param predicates Indicates filter criteria. You should define the processing logic when this parameter is null. -* @param value Indicates the data to update. This parameter can be null. -* -* @return Returns the number of data records updated. -*/ + * @brief Updates data records in the database. + * + * @param uri Indicates the path of data to update. + * @param predicates Indicates filter criteria. You should define the processing logic when this parameter is null. + * @param value Indicates the data to update. This parameter can be null. + * + * @return Returns the number of data records updated. + */ int DataShareHelper::Update(Uri &uri, const DataSharePredicates &predicates, const DataShareValuesBucket &value) { int index = INVALID_VALUE; @@ -296,13 +293,13 @@ int DataShareHelper::Update(Uri &uri, const DataSharePredicates &predicates, con } /** -* @brief Deletes one or more data records from the database. -* -* @param uri Indicates the path of the data to operate. -* @param predicates Indicates filter criteria. You should define the processing logic when this parameter is null. -* -* @return Returns the number of data records deleted. -*/ + * @brief Deletes one or more data records from the database. + * + * @param uri Indicates the path of the data to operate. + * @param predicates Indicates filter criteria. You should define the processing logic when this parameter is null. + * + * @return Returns the number of data records deleted. + */ int DataShareHelper::Delete(Uri &uri, const DataSharePredicates &predicates) { int index = INVALID_VALUE; @@ -325,14 +322,14 @@ int DataShareHelper::Delete(Uri &uri, const DataSharePredicates &predicates) } /** -* @brief Deletes one or more data records from the database. -* -* @param uri Indicates the path of data to query. -* @param predicates Indicates filter criteria. You should define the processing logic when this parameter is null. -* @param columns Indicates the columns to query. If this parameter is null, all columns are queried. -* -* @return Returns the query result. -*/ + * @brief Deletes one or more data records from the database. + * + * @param uri Indicates the path of data to query. + * @param predicates Indicates filter criteria. You should define the processing logic when this parameter is null. + * @param columns Indicates the columns to query. If this parameter is null, all columns are queried. + * + * @return Returns the query result. + */ std::shared_ptr DataShareHelper::Query(Uri &uri, const DataSharePredicates &predicates, std::vector &columns, DatashareBusinessError *businessError) { @@ -361,13 +358,13 @@ std::shared_ptr DataShareHelper::Query(Uri &uri, const DataS } /** -* @brief Obtains the MIME type matching the data specified by the URI of the data share. This method should be -* implemented by a data share. Data abilities supports general data types, including text, HTML, and JPEG. -* -* @param uri Indicates the URI of the data. -* -* @return Returns the MIME type that matches the data specified by uri. -*/ + * @brief Obtains the MIME type matching the data specified by the URI of the data share. This method should be + * implemented by a data share. Data abilities supports general data types, including text, HTML, and JPEG. + * + * @param uri Indicates the URI of the data. + * + * @return Returns the MIME type that matches the data specified by uri. + */ std::string DataShareHelper::GetType(Uri &uri) { std::string type; @@ -391,13 +388,13 @@ std::string DataShareHelper::GetType(Uri &uri) } /** -* @brief Inserts multiple data records into the database. -* -* @param uri Indicates the path of the data to operate. -* @param values Indicates the data records to insert. -* -* @return Returns the number of data records inserted. -*/ + * @brief Inserts multiple data records into the database. + * + * @param uri Indicates the path of the data to operate. + * @param values Indicates the data records to insert. + * + * @return Returns the number of data records inserted. + */ int DataShareHelper::BatchInsert(Uri &uri, const std::vector &values) { int ret = INVALID_VALUE; @@ -420,11 +417,11 @@ int DataShareHelper::BatchInsert(Uri &uri, const std::vector &dataObserver) { LOG_INFO("Start"); @@ -459,11 +456,11 @@ void DataShareHelper::RegisterObserver(const Uri &uri, const sptr &dataObserver) { LOG_INFO("Start"); @@ -493,10 +490,10 @@ void DataShareHelper::UnregisterObserver(const Uri &uri, const sptr dataObserver, bool isDescendants) + * Registers an observer to DataObsMgr specified by the given Uri. + * + * @param uri, Indicates the path of the data to operate. + * @param dataObserver, Indicates the DataShareObserver object. + * @param isDescendants, Indicates the Whether to note the change of descendants. + */ +void DataShareHelper::RegisterObserverExt(const Uri &uri, std::shared_ptr dataObserver, + bool isDescendants) { LOG_INFO("Start"); if (dataObserver == nullptr) { @@ -549,11 +546,11 @@ void DataShareHelper::RegisterObserverExt( } /** -* Deregisters an observer used for DataObsMgr specified by the given Uri. -* -* @param uri, Indicates the path of the data to operate. -* @param dataObserver, Indicates the DataShareObserver object. -*/ + * Deregisters an observer used for DataObsMgr specified by the given Uri. + * + * @param uri, Indicates the path of the data to operate. + * @param dataObserver, Indicates the DataShareObserver object. + */ void DataShareHelper::UnregisterObserverExt(const Uri &uri, std::shared_ptr dataObserver) { LOG_INFO("Start"); @@ -579,10 +576,10 @@ void DataShareHelper::UnregisterObserverExt(const Uri &uri, std::shared_ptr stubFuncMap_; + static constexpr int VALUEBUCKET_MAX_COUNT = 3000; }; } // namespace DataShare } // namespace OHOS diff --git a/data_share/frameworks/native/provider/src/datashare_stub.cpp b/data_share/frameworks/native/provider/src/datashare_stub.cpp index 531db554..459ee9ec 100644 --- a/data_share/frameworks/native/provider/src/datashare_stub.cpp +++ b/data_share/frameworks/native/provider/src/datashare_stub.cpp @@ -280,8 +280,12 @@ ErrCode DataShareStub::CmdBatchInsert(MessageParcel &data, MessageParcel &reply) LOG_ERROR("fail to ReadInt32 index"); return ERR_INVALID_VALUE; } + if (count > VALUEBUCKET_MAX_COUNT) { + return ERR_INVALID_VALUE; + } std::vector values; + values.reserve(static_cast(count)); for (int i = 0; i < count; i++) { DataShareValuesBucket value; if (!ITypesUtils::Unmarshalling(data, value)) { diff --git a/data_share/test/native/unittest/mediadatashare_test/src/mediadatashare_unit_test.cpp b/data_share/test/native/unittest/mediadatashare_test/src/mediadatashare_unit_test.cpp index 7c1569a1..22343851 100644 --- a/data_share/test/native/unittest/mediadatashare_test/src/mediadatashare_unit_test.cpp +++ b/data_share/test/native/unittest/mediadatashare_test/src/mediadatashare_unit_test.cpp @@ -1,26 +1,26 @@ /* -* Copyright (C) 2021-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. -*/ + * Copyright (C) 2021-2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ #define MLOG_TAG "DataShareUnitTest" #include "mediadatashare_unit_test.h" #include "datashare_helper.h" -#include "datashare_log.h" #include "fetch_result.h" #include "get_self_permissions.h" #include "iservice_registry.h" +#include "datashare_log.h" #include "media_file_utils.h" #include "media_library_manager.h" #include "medialibrary_errno.h" @@ -41,13 +41,13 @@ std::shared_ptr CreateDataShareHelper(int32_t system auto saManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); if (saManager == nullptr) { LOG_ERROR("CreateDataShareHelper::CreateFileExtHelper Get system ability " - "mgr failed."); + "mgr failed."); return nullptr; } auto remoteObj = saManager->GetSystemAbility(systemAbilityId); while (remoteObj == nullptr) { LOG_ERROR("CreateDataShareHelper::CreateFileExtHelper GetSystemAbility " - "Service Failed."); + "Service Failed."); return nullptr; } return DataShare::DataShareHelper::Creator(remoteObj, MEDIALIBRARY_DATA_URI); @@ -202,12 +202,8 @@ void MediaDataShareUnitTest::TearDownTestCase(void) LOG_INFO("TearDownTestCase end"); } -void MediaDataShareUnitTest::SetUp(void) -{ -} -void MediaDataShareUnitTest::TearDown(void) -{ -} +void MediaDataShareUnitTest::SetUp(void) {} +void MediaDataShareUnitTest::TearDown(void) {} HWTEST_F(MediaDataShareUnitTest, MediaDataShare_Predicates_Test_001, TestSize.Level0) { @@ -559,7 +555,7 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_Predicates_Test_021, TestSize.Le LOG_INFO("MediaDataShare_Predicates_Test_021::Start"); DataShare::DataSharePredicates predicates; predicates.EqualTo(MEDIA_DATA_DB_TITLE, "dataShareTest003"); - + std::vector operationItems = predicates.GetOperationList(); DataShare::OperationItem operationItem = operationItems[0]; EXPECT_EQ(operationItem.operation, DataShare::OperationType::EQUAL_TO); @@ -598,7 +594,7 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_Predicates_Test_024, TestSize.Le { LOG_INFO("MediaDataShare_Predicates_Test_024::Start"); DataShare::DataSharePredicates predicates; - int res = predicates.SetWhereArgs(std::vector{ "-5" }); + int res = predicates.SetWhereArgs(std::vector { "-5" }); EXPECT_EQ(res, 0); vector args = predicates.GetWhereArgs(); EXPECT_EQ(args[0], "-5"); @@ -891,7 +887,7 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_ResultSet_Test_003, TestSize.Lev auto resultSet = helper->Query(uri, predicates, columns); AppDataFwk::SharedBlock *block = nullptr; ASSERT_TRUE(resultSet != nullptr); - + bool hasBlock = resultSet->HasBlock(); EXPECT_EQ(hasBlock, true); block = resultSet->GetBlock(); @@ -1075,7 +1071,7 @@ HWTEST_F(MediaDataShareUnitTest, Insert_ConnectionNull_Test_001, TestSize.Level0 valuesBucket.Put(MEDIA_DATA_DB_TITLE, "dataShareTest006"); int value4 = 998; valuesBucket.Put(MEDIA_DATA_DB_PARENT_ID, value4); - auto resultInsert = helper->Insert(uri, valuesBucket); + auto resultInsert= helper->Insert(uri, valuesBucket); EXPECT_EQ(resultInsert, -1); auto resultGetType = helper->GetType(uri); @@ -1128,7 +1124,7 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_NotImplPredicates_Test_001, Test inColumn.push_back("dataShare_Test_001"); inColumn.push_back("dataShare_Test_002"); predicates.In(MEDIA_DATA_DB_TITLE, inColumn); - + vector notInColumn; notInColumn.push_back("dataShare_Test_003"); notInColumn.push_back("dataShare_Test_004"); @@ -1157,7 +1153,7 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_Observer_001, TestSize.Level0) sptr dataObserver; EXPECT_EQ(dataObserver, nullptr); helper->RegisterObserver(uri, dataObserver); - + DataShare::DataShareValuesBucket valuesBucket; valuesBucket.Put(MEDIA_DATA_DB_TITLE, "Datashare_Observer_Test001"); int retVal = helper->Insert(uri, valuesBucket); diff --git a/datamgr_service/services/distributeddataservice/app/distributed_data.cfg b/datamgr_service/services/distributeddataservice/app/distributed_data.cfg index 494bc79b..a42d9dc4 100644 --- a/datamgr_service/services/distributeddataservice/app/distributed_data.cfg +++ b/datamgr_service/services/distributeddataservice/app/distributed_data.cfg @@ -30,7 +30,8 @@ "apl" : "system_basic", "permission" : [ "ohos.permission.DISTRIBUTED_DATASYNC", - "ohos.permission.MANAGE_LOCAL_ACCOUNTS" + "ohos.permission.MANAGE_LOCAL_ACCOUNTS", + "ohos.permission.ACCESS_SERVICE_DM" ] } ] diff --git a/datamgr_service/services/distributeddataservice/framework/BUILD.gn b/datamgr_service/services/distributeddataservice/framework/BUILD.gn index d22d731b..7beccd12 100644 --- a/datamgr_service/services/distributeddataservice/framework/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/framework/BUILD.gn @@ -34,6 +34,12 @@ ohos_shared_library("distributeddatasvcfwk") { sources = [ "backuprule/backup_rule_manager.cpp", "checker/checker_manager.cpp", + "cloud/asset_loader.cpp", + "cloud/cloud_db.cpp", + "cloud/cloud_event.cpp", + "cloud/cloud_info.cpp", + "cloud/cloud_server.cpp", + "cloud/schema_meta.cpp", "eventcenter/event.cpp", "eventcenter/event_center.cpp", "feature/feature_system.cpp", diff --git a/datamgr_service/services/distributeddataservice/framework/cloud/cloud_event.cpp b/datamgr_service/services/distributeddataservice/framework/cloud/cloud_event.cpp index 5dd21727..0212fcc7 100644 --- a/datamgr_service/services/distributeddataservice/framework/cloud/cloud_event.cpp +++ b/datamgr_service/services/distributeddataservice/framework/cloud/cloud_event.cpp @@ -16,21 +16,22 @@ #include "cloud/cloud_event.h" namespace OHOS::DistributedData { -CloudEvent::CloudEvent(int32_t evtId, uint32_t tokenId, std::string storeName, std::string bundleName, - std::string schemaKey) - : Event(evtId), tokenId_(tokenId), storeName_(storeName), bundleName_(bundleName), schemaKey_(schemaKey) +CloudEvent::CloudEvent(int32_t evtId, uint32_t tokenId, const std::string &storeName, const std::string &bundleName, + const std::string &featureName, const std::string &schemaKey) + : Event(evtId), featureName_(featureName), tokenId_(tokenId), storeName_(storeName), bundleName_(bundleName), + schemaKey_(schemaKey) { } CloudEvent::CloudEvent(int32_t evtId, const CloudEvent &cloudEvent) - : Event(evtId), tokenId_(cloudEvent.GetTokenId()), storeName_(cloudEvent.GetStoreName()), - bundleName_(cloudEvent.GetBundleName()) + : Event(evtId), featureName_(cloudEvent.GetFeatureName()), tokenId_(cloudEvent.GetTokenId()), + storeName_(cloudEvent.GetStoreName()), bundleName_(cloudEvent.GetBundleName()) { } -//int32_t CloudEvent::GetUser() const -//{ -// return user_; -//} +std::string CloudEvent::GetFeatureName() const +{ + return featureName_; +} void CloudEvent::SetSchemaKey(std::string schemaKey) { diff --git a/datamgr_service/services/distributeddataservice/framework/cloud/cloud_server.cpp b/datamgr_service/services/distributeddataservice/framework/cloud/cloud_server.cpp index 48f1ce76..036a7229 100644 --- a/datamgr_service/services/distributeddataservice/framework/cloud/cloud_server.cpp +++ b/datamgr_service/services/distributeddataservice/framework/cloud/cloud_server.cpp @@ -29,4 +29,24 @@ bool CloudServer::RegisterCloudInstance(CloudServer *instance) instance_ = instance; return true; } + +CloudInfo CloudServer::GetServerInfo(int32_t userId) +{ + return CloudInfo(); +} + +SchemaMeta CloudServer::GetAppSchema(int32_t userId, const std::string &bundleName) +{ + return SchemaMeta(); +} + +std::shared_ptr CloudServer::ConnectAssetLoader(uint32_t tokenId, const CloudServer::Database &dbMeta) +{ + return std::shared_ptr(); +} + +std::shared_ptr CloudServer::ConnectCloudDB(uint32_t tokenId, const CloudServer::Database &dbMeta) +{ + return std::shared_ptr(); +} } // namespace OHOS::DistributedData \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_event.h b/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_event.h index 64493501..469e50fc 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_event.h +++ b/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_event.h @@ -20,19 +20,21 @@ #include "eventcenter/event.h" namespace OHOS::DistributedData { -class CloudEvent : public Event { +class API_EXPORT CloudEvent : public Event { public: enum : int32_t { - CLOUD_RDB_FEATURE_INIT = EVT_CLOUD, - CLOUD_RDB_OPEN_STORE, - CLOUD_RDB_NEED_CREATE, + FEATURE_INIT = EVT_CLOUD, + GET_SCHEMA, + NEED_CREATE, CLOUD_BUTT }; - CloudEvent(int32_t evtId, uint32_t tokenId = 0, std::string storeName = "", std::string bundleName = "", std::string schemaKey = ""); + CloudEvent(int32_t evtId, uint32_t tokenId = 0, const std::string &storeName = "", + const std::string &bundleName = "", const std::string &featureName = "relational_store", + const std::string &schemaKey = ""); CloudEvent(int32_t evtId, const CloudEvent &cloudEvent); ~CloudEvent() = default; -// int32_t GetUser() const; + std::string GetFeatureName() const; void SetSchemaKey(std::string bundleName); std::string GetSchemaKey() const; std::string GetBundleName() const; @@ -41,10 +43,10 @@ public: bool Equals(const DistributedData::Event &event) const override; private: -// int32_t user_; - std::string bundleName_; + std::string featureName_; uint32_t tokenId_; std::string storeName_; + std::string bundleName_; std::string schemaKey_; }; diff --git a/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_server.h b/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_server.h index 7fc0a9f1..2197efa6 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_server.h +++ b/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_server.h @@ -26,10 +26,11 @@ public: using Database = SchemaMeta::Database; API_EXPORT static CloudServer *GetInstance(); API_EXPORT static bool RegisterCloudInstance(CloudServer *instance); - virtual CloudInfo GetServerInfo(int32_t userId) = 0; - virtual SchemaMeta GetAppSchema(int32_t userId, const std::string &bundleName) = 0; - virtual std::shared_ptr ConnectAssetLoader(uint32_t tokenId, const Database &dbMeta) = 0; - virtual std::shared_ptr ConnectCloudDB(uint32_t tokenId, const Database &dbMeta) = 0; + + virtual CloudInfo GetServerInfo(int32_t userId); + virtual SchemaMeta GetAppSchema(int32_t userId, const std::string &bundleName); + virtual std::shared_ptr ConnectAssetLoader(uint32_t tokenId, const Database &dbMeta); + virtual std::shared_ptr ConnectCloudDB(uint32_t tokenId, const Database &dbMeta); private: static CloudServer *instance_; diff --git a/datamgr_service/services/distributeddataservice/service/BUILD.gn b/datamgr_service/services/distributeddataservice/service/BUILD.gn index d05b54c5..17f18018 100644 --- a/datamgr_service/services/distributeddataservice/service/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/service/BUILD.gn @@ -21,6 +21,7 @@ config("module_public_config") { include_dirs = [ "backup/include", "bootstrap/include", + "cloud", "config/include", "crypto/include", "datashare", @@ -52,11 +53,15 @@ ohos_shared_library("distributeddatasvc") { include_dirs = [ "../../../../data_object/frameworks/innerkitsimpl/include", "//foundation/distributeddatamgr/relational_store/interfaces/inner_api/rdb/include", + "//foundation/distributeddatamgr/relational_store/interfaces/inner_api/cloud_data/include", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/include/distributeddb", ] sources = [ "backup/src/backup_manager.cpp", "bootstrap/src/bootstrap.cpp", + "cloud/cloud_service_impl.cpp", + "cloud/cloud_service_stub.cpp", + "cloud/cloud_syncer.cpp", "config/src/config_factory.cpp", "config/src/model/backup_config.cpp", "config/src/model/checker_config.cpp", @@ -94,6 +99,7 @@ ohos_shared_library("distributeddatasvc") { "object/object_service_impl.cpp", "object/object_service_stub.cpp", "permission/src/permit_delegate.cpp", + "rdb/rdb_general_store.cpp", "rdb/rdb_notifier_proxy.cpp", "rdb/rdb_result_set_impl.cpp", "rdb/rdb_result_set_stub.cpp", @@ -130,6 +136,7 @@ ohos_shared_library("distributeddatasvc") { "huks:libhukssdk", "ipc:ipc_core", "relational_store:native_rdb", + "relational_store:cloud_data", "relational_store:rdb_data_share_adapter", "resource_management:global_resmgr", "samgr:samgr_proxy", diff --git a/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.cpp b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.cpp index 35d6ab11..0cf1ebe7 100644 --- a/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.cpp +++ b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.cpp @@ -46,7 +46,7 @@ CloudServiceImpl::Factory::~Factory() {} CloudServiceImpl::CloudServiceImpl() { - EventCenter::GetInstance().Subscribe(CloudEvent::CLOUD_RDB_FEATURE_INIT, [this](const Event &event) { + EventCenter::GetInstance().Subscribe(CloudEvent::FEATURE_INIT, [this](const Event &event) { auto &rdbEvent = static_cast(event); CloudInfo cloudInfo; cloudInfo.user = DistributedKv::AccountDelegate::GetInstance()->GetUserByToken(rdbEvent.GetTokenId()); @@ -58,7 +58,7 @@ CloudServiceImpl::CloudServiceImpl() AddSchema(cloudInfo); }); - EventCenter::GetInstance().Subscribe(CloudEvent::CLOUD_RDB_OPEN_STORE, [this](const Event &event) { + EventCenter::GetInstance().Subscribe(CloudEvent::GET_SCHEMA, [this](const Event &event) { auto &rdbEvent = static_cast(event); CloudInfo cloudInfo; cloudInfo.user = DistributedKv::AccountDelegate::GetInstance()->GetUserByToken(rdbEvent.GetTokenId()); @@ -75,7 +75,7 @@ CloudServiceImpl::CloudServiceImpl() if (!MetaDataManager::GetInstance().LoadMeta(schemaKey, schemaMeta, true)) { schemaMeta = instance->GetAppSchema(cloudInfo.user, rdbEvent.GetBundleName()); MetaDataManager::GetInstance().SaveMeta(schemaKey, schemaMeta, true); - auto finishedEvent = std::make_unique(CloudEvent::CLOUD_RDB_NEED_CREATE, rdbEvent); + auto finishedEvent = std::make_unique(CloudEvent::NEED_CREATE, rdbEvent); finishedEvent->SetSchemaKey(schemaKey); EventCenter::GetInstance().PostEvent(move(finishedEvent)); } diff --git a/datamgr_service/services/distributeddataservice/service/data_share/data_share_service_stub.cpp b/datamgr_service/services/distributeddataservice/service/data_share/data_share_service_stub.cpp index f5c2fbac..a388f8cc 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/data_share_service_stub.cpp +++ b/datamgr_service/services/distributeddataservice/service/data_share/data_share_service_stub.cpp @@ -99,7 +99,6 @@ int32_t DataShareServiceStub::OnRemoteQuery(MessageParcel &data, MessageParcel & } int status = 0; auto result = ISharedResultSet::WriteToParcel(Query(uri, predicate, columns, status), reply); - reply.WriteInt32(status); if (!ITypesUtil::Marshal(reply, status)) { ZLOGE("Marshal status:0x%{public}x", status); return IPC_STUB_WRITE_PARCEL_ERR; diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.cpp b/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.cpp index 74ddeb5f..191f2c78 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.cpp +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.cpp @@ -46,8 +46,9 @@ namespace OHOS::DistributedRdb { __attribute__((used)) RdbServiceImpl::Factory RdbServiceImpl::factory_; RdbServiceImpl::Factory::Factory() { - FeatureSystem::GetInstance().RegisterCreator("relational_store", - []() { return std::make_shared(); }); + FeatureSystem::GetInstance().RegisterCreator(RdbServiceImpl::SERVICE_NAME, []() { + return std::make_shared(); + }); AutoCache::GetInstance().RegCreator(RDB_DEVICE_COLLABORATION, [](const StoreMetaData &metaData) -> GeneralStore * { return new RdbGeneralStore(metaData); }); @@ -86,10 +87,13 @@ RdbServiceImpl::RdbServiceImpl() return ResolveAutoLaunch(identifier, param); }); - EventCenter::GetInstance().Subscribe(CloudEvent::CLOUD_RDB_NEED_CREATE, [this](const Event &event) { + EventCenter::GetInstance().Subscribe(CloudEvent::NEED_CREATE, [this](const Event &event) { auto &cloudEvent = static_cast(event); + if (cloudEvent.GetFeatureName() != "relation_store") { + return; + } DistributedData::SchemaMeta schemaMeta; - MetaDataManager::GetInstance().LoadMeta(cloudEvent.GetSchemaKey(),schemaMeta); + MetaDataManager::GetInstance().LoadMeta(cloudEvent.GetSchemaKey(), schemaMeta); //CreateDatabase(schemaMeta)TODO:根据schema创建表和trigger }); } @@ -343,10 +347,9 @@ int32_t RdbServiceImpl::DoAsync(const RdbSyncerParam ¶m, uint32_t seqNum, co if (syncer == nullptr) { return RDB_ERROR; } - return syncer->DoAsync(option, predicates, - [this, pid, seqNum] (const SyncResult& result) { - OnAsyncComplete(pid, seqNum, result); - }); + return syncer->DoAsync(option, predicates, [this, pid, seqNum](const SyncResult &result) { + OnAsyncComplete(pid, seqNum, result); + }); } std::string RdbServiceImpl::TransferStringToHex(const std::string &origStr) @@ -469,19 +472,19 @@ int32_t RdbServiceImpl::OnInitialize() { auto tokenId = IPCSkeleton::GetCallingTokenID(); auto user = AccountDelegate::GetInstance()->GetUserByToken(tokenId); - auto initEvt = std::make_unique(CloudEvent::CLOUD_RDB_FEATURE_INIT, user); + auto initEvt = std::make_unique(CloudEvent::FEATURE_INIT, user); EventCenter::GetInstance().PostEvent(std::move(initEvt)); return RDB_OK; } -int32_t RdbServiceImpl::OpenStore(const CloudParam &cloudParam) +int32_t RdbServiceImpl::GetSchema(const std::string &bundleName, const std::string &storeName) { - if (!CheckAccess(cloudParam.bundleName, cloudParam.storeName)) { + if (!CheckAccess(bundleName, storeName)) { ZLOGE("permission error"); return RDB_ERROR; } - auto event = std::make_unique(CloudEvent::CLOUD_RDB_OPEN_STORE, IPCSkeleton::GetCallingTokenID(), - cloudParam.storeName, cloudParam.bundleName); + auto event = std::make_unique(CloudEvent::GET_SCHEMA, IPCSkeleton::GetCallingTokenID(), + storeName, bundleName); EventCenter::GetInstance().PostEvent(move(event)); return 0; diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.h b/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.h index 17e12968..d8f31239 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.h +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.h @@ -58,7 +58,7 @@ public: int32_t OnInitialize() override; - int32_t OpenStore(const CloudParam &cloudParam) override; + int32_t GetSchema(const std::string &bundleName, const std::string &storeName) override; protected: int32_t DoSync(const RdbSyncerParam& param, const SyncOption& option, diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_stub.cpp b/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_stub.cpp index 83d11cdb..32fed04b 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_stub.cpp +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_stub.cpp @@ -39,14 +39,14 @@ int32_t RdbServiceStub::OnRemoteObtainDistributedTableName(MessageParcel &data, return RDB_OK; } -int32_t RdbServiceStub::OnOpenStore(MessageParcel &data, MessageParcel &reply) { - CloudParam cloudParam; - if (!ITypesUtil::Unmarshal(data, cloudParam)) { - ZLOGE("Unmarshal bundleName_:%{public}s storeName_:%{public}s", cloudParam.bundleName.c_str(), - cloudParam.storeName.c_str()); +int32_t RdbServiceStub::OnGetSchema(MessageParcel &data, MessageParcel &reply) { + std::string bundleName; + std::string storeName; + if (!ITypesUtil::Unmarshal(data, bundleName, storeName)) { + ZLOGE("Unmarshal bundleName_:%{public}s storeName_:%{public}s", bundleName.c_str(), storeName.c_str()); return IPC_STUB_INVALID_DATA_ERR; } - auto status = OpenStore(cloudParam); + auto status = GetSchema(bundleName, storeName); if (!ITypesUtil::Marshal(reply, status)) { ZLOGE("Marshal status:0x%{public}x", status); return IPC_STUB_WRITE_PARCEL_ERR; diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_stub.h b/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_stub.h index 0758ad9c..2e1af17a 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_stub.h +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_stub.h @@ -50,7 +50,7 @@ private: int32_t OnRemoteObtainDistributedTableName(MessageParcel& data, MessageParcel& reply); - int32_t OnOpenStore(MessageParcel&data, MessageParcel& reply); + int32_t OnGetSchema(MessageParcel&data, MessageParcel& reply); int32_t OnRemoteInitNotifier(MessageParcel&data, MessageParcel& reply); @@ -82,7 +82,7 @@ private: [RDB_SERVICE_CMD_REMOTE_QUERY] = &RdbServiceStub::OnRemoteDoRemoteQuery, [RDB_SERVICE_CREATE_RDB_TABLE] = &RdbServiceStub::OnRemoteDoCreateTable, [RDB_SERVICE_DESTROY_RDB_TABLE] = &RdbServiceStub::OnRemoteDoDestroyTable, - [RDB_SERVICE_CMD_OPEN_STORE] = &RdbServiceStub::OnOpenStore + [RDB_SERVICE_CMD_GET_SCHEMA] = &RdbServiceStub::OnGetSchema }; }; } // namespace OHOS::DistributedRdb diff --git a/kv_store/frameworks/common/log_print.h b/kv_store/frameworks/common/log_print.h index 274031b0..100c5fc4 100644 --- a/kv_store/frameworks/common/log_print.h +++ b/kv_store/frameworks/common/log_print.h @@ -26,7 +26,7 @@ static inline OHOS::HiviewDFX::HiLogLabel LogLabel() { return { LOG_CORE, 0xD001610, "ZDDS" }; } -} // namespace DistributedKv +} // end namespace DistributesdKv namespace DistributedData { static inline OHOS::HiviewDFX::HiLogLabel LogLabel() @@ -79,16 +79,16 @@ static inline OHOS::HiviewDFX::HiLogLabel LogLabel() } // end namespace OHOS #define ZLOGD(fmt, ...) \ - OHOS::HiviewDFX::HiLog::Debug(LogLabel(), LOG_TAG "::%{public}s: " fmt, __FUNCTION__, ##__VA_ARGS__) + OHOS::HiviewDFX::HiLog::Debug(LogLabel(), LOG_TAG "::%{public}s: " fmt, __FUNCTION__, ##__VA_ARGS__) #define ZLOGI(fmt, ...) \ - OHOS::HiviewDFX::HiLog::Info(LogLabel(), LOG_TAG "::%{public}s: " fmt, __FUNCTION__, ##__VA_ARGS__) + OHOS::HiviewDFX::HiLog::Info(LogLabel(), LOG_TAG "::%{public}s: " fmt, __FUNCTION__, ##__VA_ARGS__) #define ZLOGW(fmt, ...) \ - OHOS::HiviewDFX::HiLog::Warn(LogLabel(), LOG_TAG "::%{public}s: " fmt, __FUNCTION__, ##__VA_ARGS__) + OHOS::HiviewDFX::HiLog::Warn(LogLabel(), LOG_TAG "::%{public}s: " fmt, __FUNCTION__, ##__VA_ARGS__) #define ZLOGE(fmt, ...) \ - OHOS::HiviewDFX::HiLog::Error(LogLabel(), LOG_TAG "::%{public}s: " fmt, __FUNCTION__, ##__VA_ARGS__) + OHOS::HiviewDFX::HiLog::Error(LogLabel(), LOG_TAG "::%{public}s: " fmt, __FUNCTION__, ##__VA_ARGS__) #else #error // unknown system diff --git a/mock/include/CMakeLists.txt b/mock/include/CMakeLists.txt index efa79ace..4041c7a0 100644 --- a/mock/include/CMakeLists.txt +++ b/mock/include/CMakeLists.txt @@ -101,7 +101,7 @@ include_directories(${MOCK_DIR}/innerkits/napi/ace_napi/include/napi) include_directories(${MOCK_DIR}/innerkits/device_profile_core/distributed_device_profile_client/include) include_directories(${MOCK_DIR}/innerkits/hiview/libfaultlogger/include) include_directories(${MOCK_DIR}/innerkits/syscap_codec/syscap_interface_shared/include) -include_directories(${MOCK_DIR}/innerkits/ipc/ipc_single/include) +#include_directories(${MOCK_DIR}/innerkits/ipc/ipc_single/include) include_directories(${MOCK_DIR}/innerkits/ipc/ipc_core/include) include_directories(${MOCK_DIR}/innerkits/ipc/libdbinder/include) include_directories(${MOCK_DIR}/innerkits/i18n/zone_util/include) diff --git a/mock/innerkits/ability_runtime/runtime/include/js_runtime.h b/mock/innerkits/ability_runtime/runtime/include/js_runtime.h index a31a23cb..2127c171 100644 --- a/mock/innerkits/ability_runtime/runtime/include/js_runtime.h +++ b/mock/innerkits/ability_runtime/runtime/include/js_runtime.h @@ -50,20 +50,32 @@ public: return Language::JS; } - std::unique_ptr LoadModule( - const std::string& moduleName, const std::string& modulePath, bool esmodule = false); - std::unique_ptr LoadModule(const std::string &moduleName, const std::string &modulePath, - bool hapPath, bool esmodule = false); + std::unique_ptr LoadModule(const std::string& moduleName, const std::string& modulePath, + const std::string& hapPath, bool esmodule = false, bool useCommonChunk = false); std::unique_ptr LoadSystemModule( const std::string& moduleName, NativeValue* const* argv = nullptr, size_t argc = 0); void PostTask(const std::function& task, const std::string& name, int64_t delayTime); void RemoveTask(const std::string& name); void DumpHeapSnapshot(bool isPrivate) override; - std::string BuildJsStackTrace() override; +// bool BuildJsStackInfoList(uint32_t tid, std::vector& jsFrames) override; void NotifyApplicationState(bool isBackground) override; + bool RunSandboxScript(const std::string& path, const std::string& hapPath); + bool RunScript(const std::string& path, const std::string& hapPath, bool useCommonChunk = false); - bool RunSandboxScript(const std::string& path); - virtual bool RunScript(const std::string& path) = 0; + bool LoadScript(const std::string& path, std::vector* buffer = nullptr, bool isBundle = false); + + NativeEngine* GetNativeEnginePointer() const; + + void UpdateModuleNameAndAssetPath(const std::string& moduleName); + static bool GetFileBuffer(const std::string& filePath, std::string& fileFullName, std::vector& buffer); + void StartDebugMode(bool needBreakPoint) override; + void PreloadSystemModule(const std::string &moduleName) override; + void FinishPreload() override; + bool LoadRepairPatch(const std::string &patchFile, const std::string &baseFile) override; + bool NotifyHotReloadPage() override; + bool UnLoadRepairPatch(const std::string &patchFile) override; + void UpdateExtensionType(int32_t extensionType) override; + void RegisterQuickFixQueryFunc(const std::map& moduleAndPath) override; protected: JsRuntime() = default; diff --git a/mock/innerkits/ability_runtime/runtime/include/runtime.h b/mock/innerkits/ability_runtime/runtime/include/runtime.h index cb03c5b1..8280cbbe 100644 --- a/mock/innerkits/ability_runtime/runtime/include/runtime.h +++ b/mock/innerkits/ability_runtime/runtime/include/runtime.h @@ -17,6 +17,7 @@ #define FOUNDATION_OHOS_ABILITYRUNTIME_RUNTIME_H #include +#include namespace OHOS { namespace AppExecFwk { @@ -45,10 +46,17 @@ public: virtual Language GetLanguage() const = 0; - virtual void StartDebugMode(bool needBreakPoint, int32_t instanceId = 0) = 0; - virtual std::string BuildJsStackTrace() = 0; + virtual void StartDebugMode(bool needBreakPoint) = 0; +// virtual bool BuildJsStackInfoList(uint32_t tid, std::vector& jsFrames) = 0; virtual void DumpHeapSnapshot(bool isPrivate) = 0; virtual void NotifyApplicationState(bool isBackground) = 0; + virtual void PreloadSystemModule(const std::string& moduleName) = 0; + virtual void FinishPreload() = 0; + virtual bool LoadRepairPatch(const std::string& patchFile, const std::string& baseFile) = 0; + virtual bool NotifyHotReloadPage() = 0; + virtual bool UnLoadRepairPatch(const std::string& patchFile) = 0; + virtual void UpdateExtensionType(int32_t extensionType) = 0; + virtual void RegisterQuickFixQueryFunc(const std::map& moduleAndPath) = 0; Runtime(const Runtime&) = delete; Runtime(Runtime&&) = delete; diff --git a/mock/innerkits/appexecfwk_base/include/ability_info.h b/mock/innerkits/appexecfwk_base/include/ability_info.h index 8a31b57d..81e34796 100644 --- a/mock/innerkits/appexecfwk_base/include/ability_info.h +++ b/mock/innerkits/appexecfwk_base/include/ability_info.h @@ -159,7 +159,6 @@ struct CompatibleAbilityInfo : public Parcelable { virtual bool Marshalling(Parcel& parcel) const override; static CompatibleAbilityInfo* Unmarshalling(Parcel& parcel); - void CopyToDest(CompatibleAbilityInfo& dest) const; void ConvertToAbilityInfo(AbilityInfo& abilityInfo) const; }; @@ -182,7 +181,6 @@ struct AbilityInfo : public Parcelable { std::string srcPath; std::string srcLanguage = "js"; std::vector permissions; - bool hapPath; std::string process; std::vector deviceTypes; @@ -215,6 +213,7 @@ struct AbilityInfo : public Parcelable { std::string codePath; // ability main code path with name std::string resourcePath; // resource path for resource init + std::string hapPath; std::string srcEntrance; std::vector metadata; @@ -230,6 +229,8 @@ struct AbilityInfo : public Parcelable { int32_t startWindowBackgroundId; // whether to display in the missions list bool excludeFromMissions = false; + // whether to support recover UI interface + bool recoverable = false; // support windows mode std::vector windowModes; @@ -239,6 +240,9 @@ struct AbilityInfo : public Parcelable { uint32_t minWindowWidth = 0; uint32_t maxWindowHeight = 0; uint32_t minWindowHeight = 0; + // for NAPI, save self query cache + int32_t uid = -1; + CompileMode compileMode = CompileMode::JS_BUNDLE; // unused std::string originalBundleName; @@ -258,7 +262,6 @@ struct AbilityInfo : public Parcelable { AbilitySubType subType = AbilitySubType::UNSPECIFIED; std::string libPath; std::string deviceId; - CompileMode compileMode = CompileMode::JS_BUNDLE; bool ReadFromParcel(Parcel &parcel); virtual bool Marshalling(Parcel &parcel) const override; diff --git a/mock/innerkits/bundle_framework/appexecfwk_base/include/ability_info.h b/mock/innerkits/bundle_framework/appexecfwk_base/include/ability_info.h index eb1c98d5..23bbbf61 100644 --- a/mock/innerkits/bundle_framework/appexecfwk_base/include/ability_info.h +++ b/mock/innerkits/bundle_framework/appexecfwk_base/include/ability_info.h @@ -33,6 +33,15 @@ enum AbilityInfoFlag { GET_ABILITY_INFO_WITH_DISABLE = 0x00000100, }; +enum class GetAbilityInfoFlag { + GET_ABILITY_INFO_DEFAULT = 0x00000000, + GET_ABILITY_INFO_WITH_PERMISSION = 0x00000001, + GET_ABILITY_INFO_WITH_APPLICATION = 0x00000002, + GET_ABILITY_INFO_WITH_METADATA = 0x00000004, + GET_ABILITY_INFO_WITH_DISABLE = 0x00000008, + GET_ABILITY_INFO_ONLY_SYSTEM_APP = 0x00000010, +}; + enum class AbilityType { UNKNOWN = 0, PAGE, @@ -79,15 +88,9 @@ enum class DisplayOrientation { enum class LaunchMode { SINGLETON = 0, STANDARD, // support more than one instance - SINGLETOP, SPECIFIED, }; -enum class CompileMode { - JS_BUNDLE = 0, - ES_MODULE, -}; - enum class SupportWindowMode { FULLSCREEN = 0, SPLIT, @@ -159,7 +162,6 @@ struct CompatibleAbilityInfo : public Parcelable { virtual bool Marshalling(Parcel& parcel) const override; static CompatibleAbilityInfo* Unmarshalling(Parcel& parcel); - void CopyToDest(CompatibleAbilityInfo& dest) const; void ConvertToAbilityInfo(AbilityInfo& abilityInfo) const; }; @@ -214,6 +216,7 @@ struct AbilityInfo : public Parcelable { std::string codePath; // ability main code path with name std::string resourcePath; // resource path for resource init + std::string hapPath; std::string srcEntrance; std::vector metadata; @@ -229,6 +232,8 @@ struct AbilityInfo : public Parcelable { int32_t startWindowBackgroundId; // whether to display in the missions list bool excludeFromMissions = false; + // whether to support recover UI interface + bool recoverable = false; // support windows mode std::vector windowModes; @@ -238,6 +243,9 @@ struct AbilityInfo : public Parcelable { uint32_t minWindowWidth = 0; uint32_t maxWindowHeight = 0; uint32_t minWindowHeight = 0; + // for NAPI, save self query cache + int32_t uid = -1; + CompileMode compileMode = CompileMode::JS_BUNDLE; // unused std::string originalBundleName; @@ -257,7 +265,6 @@ struct AbilityInfo : public Parcelable { AbilitySubType subType = AbilitySubType::UNSPECIFIED; std::string libPath; std::string deviceId; - CompileMode compileMode = CompileMode::JS_BUNDLE; bool ReadFromParcel(Parcel &parcel); virtual bool Marshalling(Parcel &parcel) const override; diff --git a/mock/innerkits/bundle_framework/appexecfwk_base/include/appexecfwk_errors.h b/mock/innerkits/bundle_framework/appexecfwk_base/include/appexecfwk_errors.h index 0b6094e7..586e5a1e 100644 --- a/mock/innerkits/bundle_framework/appexecfwk_base/include/appexecfwk_errors.h +++ b/mock/innerkits/bundle_framework/appexecfwk_base/include/appexecfwk_errors.h @@ -38,6 +38,7 @@ enum { ERR_APPEXECFWK_PARCEL_ERROR, ERR_APPEXECFWK_FAILED_SERVICE_DIED, ERR_APPEXECFWK_OPERATION_TIME_OUT, + ERR_APPEXECFWK_SERVICE_INTERNAL_ERROR, }; // Error code for AppMgr @@ -95,6 +96,19 @@ enum { ERR_APPEXECFWK_INSTALL_TYPE_ERROR, ERR_APPEXECFWK_INSTALL_SDK_INCOMPATIBLE, ERR_APPEXECFWK_INSTALL_SO_INCOMPATIBLE, + ERR_APPEXECFWK_INSTALL_AN_INCOMPATIBLE, + ERR_APPEXECFWK_INSTALL_NOT_UNIQUE_DISTRO_MODULE_NAME, + ERR_APPEXECFWK_INSTALL_INCONSISTENT_MODULE_NAME, + ERR_APPEXECFWK_INSTALL_SINGLETON_INCOMPATIBLE, + ERR_APPEXECFWK_INSTALL_DEVICE_TYPE_NOT_SUPPORTED, + ERR_APPEXECFWK_INSTALL_COPY_HAP_FAILED, + ERR_APPEXECFWK_INSTALL_DEPENDENT_MODULE_NOT_EXIST, + ERR_APPEXECFWK_INSTALL_ASAN_ENABLED_NOT_SAME, + ERR_APPEXECFWK_INSTALL_ASAN_NOT_SUPPORT, + ERR_APPEXECFWK_BUNDLE_TYPE_NOT_SAME, + ERR_APPEXECFWK_INSTALL_SHARE_APP_LIBRARY_NOT_ALLOWED, + ERR_APPEXECFWK_INSTALL_COMPATIBLE_POLICY_NOT_SAME, + ERR_APPEXECFWK_INSTALL_FILE_IS_SHARED_LIBRARY, // signature errcode ERR_APPEXECFWK_INSTALL_FAILED_INVALID_SIGNATURE_FILE_PATH = 8519740, @@ -130,6 +144,8 @@ enum { ERR_APPEXECFWK_SANDBOX_INSTALL_NO_SANDBOX_APP_INFO, ERR_APPEXECFWK_SANDBOX_INSTALL_UNKNOWN_INSTALL_TYPE, ERR_APPEXECFWK_SANDBOX_INSTALL_DELETE_APP_INDEX_FAILED, + ERR_APPEXECFWK_SANDBOX_APP_NOT_SUPPORTED, + ERR_APPEXECFWK_SANDBOX_INSTALL_GET_PERMISSIONS_FAILED, // sandbox app query ERR_APPEXECFWK_SANDBOX_QUERY_PARAM_ERROR, @@ -148,7 +164,10 @@ enum { ERR_APPEXECFWK_PARSE_PROFILE_MISSING_PROP, ERR_APPEXECFWK_PARSE_PERMISSION_ERROR, ERR_APPEXECFWK_PARSE_PROFILE_PROP_CHECK_ERROR, + ERR_APPEXECFWK_PARSE_PROFILE_PROP_SIZE_CHECK_ERROR, ERR_APPEXECFWK_PARSE_RPCID_FAILED, + ERR_APPEXECFWK_PARSE_NATIVE_SO_FAILED, + ERR_APPEXECFWK_PARSE_AN_FAILED, ERR_APPEXECFWK_INSTALLD_PARAM_ERROR, ERR_APPEXECFWK_INSTALLD_GET_PROXY_ERROR, @@ -162,6 +181,7 @@ enum { ERR_APPEXECFWK_INSTALLD_MOVE_FILE_FAILED, ERR_APPEXECFWK_INSTALLD_COPY_FILE_FAILED, ERR_APPEXECFWK_INSTALLD_MKDIR_FAILED, + ERR_APPEXECFWK_INSTALLD_PERMISSION_DENIED, ERR_APPEXECFWK_UNINSTALL_SYSTEM_APP_ERROR, ERR_APPEXECFWK_UNINSTALL_KILLING_APP_ERROR, @@ -171,6 +191,9 @@ enum { ERR_APPEXECFWK_UNINSTALL_BUNDLE_MGR_SERVICE_ERROR, ERR_APPEXECFWK_UNINSTALL_MISSING_INSTALLED_BUNDLE, ERR_APPEXECFWK_UNINSTALL_MISSING_INSTALLED_MODULE, + ERR_APPEXECFWK_UNINSTALL_SHARE_APP_LIBRARY_IS_NOT_EXIST, + ERR_APPEXECFWK_UNINSTALL_SHARE_APP_LIBRARY_IS_RELIED, + ERR_APPEXECFWK_UNINSTALL_BUNDLE_IS_SHARED_LIBRARY, ERR_APPEXECFWK_FAILED_GET_INSTALLER_PROXY, ERR_APPEXECFWK_FAILED_GET_BUNDLE_INFO, @@ -178,17 +201,142 @@ enum { ERR_APPEXECFWK_FAILED_GET_RESOURCEMANAGER, ERR_APPEXECFWK_FAILED_GET_REMOTE_PROXY, ERR_APPEXECFWK_PERMISSION_DENIED, + ERR_APPEXECFWK_INPUT_WRONG_TYPE_FILE, + ERR_APPEXECFWK_ENCODE_BASE64_FILE_FAILED, ERR_APPEXECFWK_RECOVER_GET_BUNDLEPATH_ERROR = APPEXECFWK_BUNDLEMGR_ERR_OFFSET + 0x0201, // 8520193 ERR_APPEXECFWK_RECOVER_INVALID_BUNDLE_NAME, + ERR_APPEXECFWK_RECOVER_NOT_ALLOWED, ERR_APPEXECFWK_USER_NOT_EXIST = APPEXECFWK_BUNDLEMGR_ERR_OFFSET + 0x0301, - ERR_APPEXECFWK_USER_CREATE_FALIED, - ERR_APPEXECFWK_USER_REMOVE_FALIED, + ERR_APPEXECFWK_USER_CREATE_FAILED, + ERR_APPEXECFWK_USER_REMOVE_FAILED, ERR_APPEXECFWK_USER_NOT_INSTALL_HAP, // error code in prebundle sacn - ERR_APPEXECFWK_PARSE_FILE_FAILED + ERR_APPEXECFWK_PARSE_FILE_FAILED, + + // debug mode + ERR_BUNDLEMANAGER_SET_DEBUG_MODE_INTERNAL_ERROR, + ERR_BUNDLEMANAGER_SET_DEBUG_MODE_PARCEL_ERROR, + ERR_BUNDLEMANAGER_SET_DEBUG_MODE_SEND_REQUEST_ERROR, + ERR_BUNDLEMANAGER_SET_DEBUG_MODE_UID_CHECK_FAILED, + ERR_BUNDLEMANAGER_SET_DEBUG_MODE_INVALID_PARAM, + + // overlay installation errcode + ERR_BUNDLEMANAGER_OVERLAY_INSTALLATION_FAILED_INTERNAL_ERROR = 8520600, + ERR_BUNDLEMANAGER_OVERLAY_INSTALLATION_FAILED_INVALID_BUNDLE_NAME, + ERR_BUNDLEMANAGER_OVERLAY_INSTALLATION_FAILED_INVALID_MODULE_NAME, + ERR_BUNDLEMANAGER_OVERLAY_INSTALLATION_FAILED_ERROR_HAP_TYPE, + ERR_BUNDLEMANAGER_OVERLAY_INSTALLATION_FAILED_ERROR_BUNDLE_TYPE, + ERR_BUNDLEMANAGER_OVERLAY_INSTALLATION_FAILED_TARGET_BUNDLE_NAME_MISSED, + ERR_BUNDLEMANAGER_OVERLAY_INSTALLATION_FAILED_TARGET_MODULE_NAME_MISSED, + ERR_BUNDLEMANAGER_OVERLAY_INSTALLATION_FAILED_TARGET_BUNDLE_NAME_NOT_SAME, + ERR_BUNDLEMANAGER_OVERLAY_INSTALLATION_FAILED_INTERNAL_EXTERNAL_OVERLAY_EXISTED_SIMULTANEOUSLY, + ERR_BUNDLEMANAGER_OVERLAY_INSTALLATION_FAILED_TARGET_PRIORITY_NOT_SAME, + ERR_BUNDLEMANAGER_OVERLAY_INSTALLATION_FAILED_INVALID_PRIORITY, + ERR_BUNDLEMANAGER_OVERLAY_INSTALLATION_FAILED_INCONSISTENT_VERSION_CODE, + ERR_BUNDLEMANAGER_OVERLAY_INSTALLATION_FAILED_SERVICE_EXCEPTION, + ERR_BUNDLEMANAGER_OVERLAY_INSTALLATION_FAILED_BUNDLE_NAME_SAME_WITH_TARGET_BUNDLE_NAME, + ERR_BUNDLEMANAGER_OVERLAY_INSTALLATION_FAILED_NO_SYSTEM_APPLICATION_FOR_EXTERNAL_OVERLAY, + ERR_BUNDLEMANAGER_OVERLAY_INSTALLATION_FAILED_DIFFERENT_SIGNATURE_CERTIFICATE, + ERR_BUNDLEMANAGER_OVERLAY_INSTALLATION_FAILED_TARGET_BUNDLE_IS_OVERLAY_BUNDLE, + ERR_BUNDLEMANAGER_OVERLAY_INSTALLATION_FAILED_TARGET_MODULE_IS_OVERLAY_MODULE, + ERR_BUNDLEMANAGER_OVERLAY_INSTALLATION_FAILED_OVERLAY_TYPE_NOT_SAME, + ERR_BUNDLEMANAGER_OVERLAY_INSTALLATION_FAILED_INVALID_BUNDLE_DIR, + ERR_BUNDLEMANAGER_OVERLAY_INSTALLATION_FAILED_TARGET_BUNDLE_IS_NOT_STAGE_MODULE, + ERR_BUNDLEMANAGER_OVERLAY_INSTALLATION_FAILED_TARGET_BUNDLE_IS_SERVICE, + + ERR_BUNDLEMANAGER_OVERLAY_QUERY_FAILED_PARAM_ERROR, + ERR_BUNDLEMANAGER_OVERLAY_QUERY_FAILED_MISSING_OVERLAY_BUNDLE, + ERR_BUNDLEMANAGER_OVERLAY_QUERY_FAILED_MISSING_OVERLAY_MODULE, + ERR_BUNDLEMANAGER_OVERLAY_QUERY_FAILED_NON_OVERLAY_BUNDLE, + ERR_BUNDLEMANAGER_OVERLAY_QUERY_FAILED_NON_OVERLAY_MODULE, + ERR_BUNDLEMANAGER_OVERLAY_QUERY_FAILED_BUNDLE_NOT_INSTALLED_AT_SPECIFIED_USERID, + ERR_BUNDLEMANAGER_OVERLAY_QUERY_FAILED_TARGET_BUNDLE_NOT_EXISTED, + ERR_BUNDLEMANAGER_OVERLAY_QUERY_FAILED_TARGET_MODULE_NOT_EXISTED, + ERR_BUNDLEMANAGER_OVERLAY_QUERY_FAILED_NO_OVERLAY_BUNDLE_INFO, + ERR_BUNDLEMANAGER_OVERLAY_QUERY_FAILED_NO_OVERLAY_MODULE_INFO, + ERR_BUNDLEMANAGER_OVERLAY_QUERY_FAILED_PERMISSION_DENIED, + ERR_BUNDLEMANAGER_OVERLAY_QUERY_FAILED_TARGET_MODULE_IS_OVERLAY_MODULE, + ERR_BUNDLEMANAGER_OVERLAY_QUERY_FAILED_TARGET_BUNDLE_IS_OVERLAY_BUNDLE, + ERR_BUNDLEMANAGER_OVERLAY_SET_OVERLAY_PARAM_ERROR, + + // quick fix errcode + ERR_BUNDLEMANAGER_QUICK_FIX_INTERNAL_ERROR = APPEXECFWK_BUNDLEMGR_ERR_OFFSET + 0x0401, // 8520705 + ERR_BUNDLEMANAGER_QUICK_FIX_PARAM_ERROR, + ERR_BUNDLEMANAGER_QUICK_FIX_PROFILE_PARSE_FAILED, + ERR_BUNDLEMANAGER_QUICK_FIX_BUNDLE_NAME_NOT_SAME, + ERR_BUNDLEMANAGER_QUICK_FIX_VERSION_CODE_NOT_SAME, + ERR_BUNDLEMANAGER_QUICK_FIX_VERSION_NAME_NOT_SAME, + ERR_BUNDLEMANAGER_QUICK_FIX_PATCH_VERSION_CODE_NOT_SAME, + ERR_BUNDLEMANAGER_QUICK_FIX_PATCH_VERSION_NAME_NOT_SAME, + ERR_BUNDLEMANAGER_QUICK_FIX_PATCH_TYPE_NOT_SAME, + ERR_BUNDLEMANAGER_QUICK_FIX_MODULE_NAME_SAME, + ERR_BUNDLEMANAGER_QUICK_FIX_UNKNOWN_QUICK_FIX_TYPE, + ERR_BUNDLEMANAGER_QUICK_FIX_SO_INCOMPATIBLE, + ERR_BUNDLEMANAGER_QUICK_FIX_BUNDLE_NAME_NOT_EXIST, + ERR_BUNDLEMANAGER_QUICK_FIX_MODULE_NAME_NOT_EXIST, + ERR_BUNDLEMANAGER_QUICK_FIX_SIGNATURE_INFO_NOT_SAME, + ERR_BUNDLEMANAGER_QUICK_FIX_ADD_HQF_FAILED, // 8520720 + ERR_BUNDLEMANAGER_QUICK_FIX_SAVE_APP_QUICK_FIX_FAILED, + ERR_BUNDLEMANAGER_QUICK_FIX_VERSION_CODE_ERROR, + ERR_BUNDLEMANAGER_QUICK_FIX_EXTRACT_DIFF_FILES_FAILED, + ERR_BUNDLEMANAGER_QUICK_FIX_APPLY_DIFF_PATCH_FAILED, + ERR_BUNDLEMANAGER_QUICK_FIX_NO_PATCH_IN_DATABASE, + ERR_BUNDLEMANAGER_QUICK_FIX_INVALID_PATCH_STATUS, + ERR_BUNDLEMANAGER_QUICK_FIX_NOT_EXISTED_BUNDLE_INFO, + ERR_BUNDLEMANAGER_QUICK_FIX_REMOVE_PATCH_PATH_FAILED, + ERR_BUNDLEMANAGER_QUICK_FIX_CREATE_PATCH_PATH_FAILED, + ERR_BUNDLEMANAGER_QUICK_FIX_MOVE_PATCH_FILE_FAILED, // 8520730 + ERR_BUNDLEMANAGER_QUICK_FIX_HOT_RELOAD_NOT_SUPPORT_RELEASE_BUNDLE, + ERR_BUNDLEMANAGER_QUICK_FIX_PATCH_ALREADY_EXISTED, + ERR_BUNDLEMANAGER_QUICK_FIX_HOT_RELOAD_ALREADY_EXISTED, + ERR_BUNDLEMANAGER_QUICK_FIX_NO_PATCH_INFO_IN_BUNDLE_INFO, + ERR_BUNDLEMANAGER_QUICK_FIX_OLD_PATCH_OR_HOT_RELOAD_IN_DB, + ERR_BUNDLEMANAGER_QUICK_FIX_SEND_REQUEST_FAILED, + ERR_BUNDLEMANAGER_QUICK_FIX_REAL_PATH_FAILED, + ERR_BUNDLEMANAGER_QUICK_FIX_INVALID_PATH, + ERR_BUNDLEMANAGER_QUICK_FIX_OPEN_SOURCE_FILE_FAILED, + ERR_BUNDLEMANAGER_QUICK_FIX_CREATE_FD_FAILED, + ERR_BUNDLEMANAGER_QUICK_FIX_INVALID_TARGET_DIR, + ERR_BUNDLEMANAGER_QUICK_FIX_CREATE_TARGET_DIR_FAILED, + ERR_BUNDLEMANAGER_QUICK_FIX_PERMISSION_DENIED, + ERR_BUNDLEMANAGER_QUICK_FIX_WRITE_FILE_FAILED, + + ERR_BUNDLE_MANAGER_APP_CONTROL_INTERNAL_ERROR = APPEXECFWK_BUNDLEMGR_ERR_OFFSET + 0x0501, // 8520961 + ERR_BUNDLE_MANAGER_APP_CONTROL_PERMISSION_DENIED, + ERR_BUNDLE_MANAGER_APP_CONTROL_RULE_TYPE_INVALID, + ERR_BUNDLE_MANAGER_BUNDLE_NOT_SET_CONTROL, + ERR_BUNDLE_MANAGER_APP_CONTROL_DISALLOWED_INSTALL, + ERR_BUNDLE_MANAGER_APP_CONTROL_DISALLOWED_UNINSTALL, + // query errcode + ERR_BUNDLE_MANAGER_INTERNAL_ERROR = APPEXECFWK_BUNDLEMGR_ERR_OFFSET + 0x0601, // 8521217 + ERR_BUNDLE_MANAGER_INVALID_PARAMETER, + ERR_BUNDLE_MANAGER_INVALID_USER_ID, + ERR_BUNDLE_MANAGER_BUNDLE_NOT_EXIST, + ERR_BUNDLE_MANAGER_ABILITY_NOT_EXIST, + ERR_BUNDLE_MANAGER_MODULE_NOT_EXIST, + ERR_BUNDLE_MANAGER_ABILITY_DISABLED, + ERR_BUNDLE_MANAGER_APPLICATION_DISABLED, + ERR_BUNDLE_MANAGER_PARAM_ERROR, + ERR_BUNDLE_MANAGER_PERMISSION_DENIED, + ERR_BUNDLE_MANAGER_IPC_TRANSACTION, + ERR_BUNDLE_MANAGER_GLOBAL_RES_MGR_ENABLE_DISABLED, + ERR_BUNDLE_MANAGER_CAN_NOT_CLEAR_USER_DATA, + ERR_BUNDLE_MANAGER_QUERY_PERMISSION_DEFINE_FAILED, + ERR_BUNDLE_MANAGER_DEVICE_ID_NOT_EXIST, + ERR_BUNDLE_MANAGER_PROFILE_NOT_EXIST, + ERR_BUNDLE_MANAGER_INVALID_UID, + ERR_BUNDLE_MANAGER_INVALID_HAP_PATH, + ERR_BUNDLE_MANAGER_DEFAULT_APP_NOT_EXIST, + ERR_BUNDLE_MANAGER_INVALID_TYPE, + ERR_BUNDLE_MANAGER_ABILITY_AND_TYPE_MISMATCH, + ERR_BUNDLE_MANAGER_SYSTEM_API_DENIED, + // zlib errcode + ERR_ZLIB_SRC_FILE_DISABLED, + ERR_ZLIB_DEST_FILE_DISABLED, + ERR_ZLIB_SERVICE_DISABLED, }; // Error code for Hidump diff --git a/mock/innerkits/bundle_framework/appexecfwk_base/include/application_info.h b/mock/innerkits/bundle_framework/appexecfwk_base/include/application_info.h index 12460bcb..56b6e0d6 100644 --- a/mock/innerkits/bundle_framework/appexecfwk_base/include/application_info.h +++ b/mock/innerkits/bundle_framework/appexecfwk_base/include/application_info.h @@ -27,7 +27,8 @@ namespace OHOS { namespace AppExecFwk { namespace { - const std::string AVAILABLELEVEL_NORMAL = "normal"; + static const std::string AVAILABLELEVEL_NORMAL = "normal"; + static const std::string DEFAULT_ENTITY_TYPE = "unspecified"; } enum ApplicationFlag { GET_BASIC_APPLICATION_INFO = 0x00000000, @@ -38,6 +39,24 @@ enum ApplicationFlag { GET_ALL_APPLICATION_INFO = 0xFFFF0000, }; +enum class GetApplicationFlag { + GET_APPLICATION_INFO_DEFAULT = 0x00000000, + GET_APPLICATION_INFO_WITH_PERMISSION = 0x00000001, + GET_APPLICATION_INFO_WITH_METADATA = 0x00000002, + GET_APPLICATION_INFO_WITH_DISABLE = 0x00000004, +}; + +enum class BundleType { + APP = 0, + ATOMIC_SERVICE = 1, +}; + +enum class CompatiblePolicy { + NORMAL = 0, + BACK_COMPATIBLE = 1, + PRECISE_MATCH = 2, +}; + struct Metadata : public Parcelable { std::string name; std::string value; @@ -140,10 +159,17 @@ struct ApplicationInfo : public Parcelable { bool singleton = false; bool userDataClearable = true; bool accessible = false; + bool runningResourcesApply = false; + bool associatedWakeUp = false; + bool hideDesktopIcon = false; + bool formVisibleNotify = false; + std::vector allowCommonEvent; bool isSystemApp = false; bool isLauncherApp = false; bool isFreeInstallApp = false; + bool asanEnabled = false; + std::string asanLogPath; std::string codePath; std::string dataDir; @@ -155,7 +181,7 @@ struct ApplicationInfo : public Parcelable { bool debug = false; std::string deviceId; bool distributedNotificationEnabled = true; - std::string entityType; + std::string entityType = DEFAULT_ENTITY_TYPE; std::string process; int32_t supportedModes = 0; // returns 0 if the application does not support the driving mode std::string vendor; @@ -168,12 +194,15 @@ struct ApplicationInfo : public Parcelable { // user related fields, assign when calling the get interface uint32_t accessTokenId = 0; + uint64_t accessTokenIdEx = 0; bool enabled = false; int32_t uid = -1; // native so std::string nativeLibraryPath; std::string cpuAbi; + std::string arkNativeFilePath; + std::string arkNativeFileAbi; // assign when calling the get interface std::vector permissions; @@ -196,12 +225,27 @@ struct ApplicationInfo : public Parcelable { // switch bool multiProjects = false; + // app detail ability + bool needAppDetail = false; + std::string appDetailAbilityLibraryPath; + + // overlay installation + std::string targetBundleName; + int32_t targetPriority; + int32_t overlayState; + + bool split = true; + BundleType bundleType = BundleType::APP; + + CompatiblePolicy compatiblePolicy = CompatiblePolicy::NORMAL; + bool ReadFromParcel(Parcel &parcel); bool ReadMetaDataFromParcel(Parcel &parcel); virtual bool Marshalling(Parcel &parcel) const override; static ApplicationInfo *Unmarshalling(Parcel &parcel); void Dump(std::string prefix, int fd); void ConvertToCompatibleApplicationInfo(CompatibleApplicationInfo& compatibleApplicationInfo) const; + bool CheckNeedPreload(const std::string &moduleName) const; }; } // namespace AppExecFwk } // namespace OHOS diff --git a/relational_store/frameworks/native/rdb/include/rdb_manager.h b/mock/innerkits/bundle_framework/appexecfwk_base/include/bundle_common_event.h similarity index 38% rename from relational_store/frameworks/native/rdb/include/rdb_manager.h rename to mock/innerkits/bundle_framework/appexecfwk_base/include/bundle_common_event.h index 5167069a..ec4d5cb6 100644 --- a/relational_store/frameworks/native/rdb/include/rdb_manager.h +++ b/mock/innerkits/bundle_framework/appexecfwk_base/include/bundle_common_event.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Huawei Device Co., Ltd. + * 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 @@ -13,20 +13,24 @@ * limitations under the License. */ -#ifndef DISTRIBUTED_RDB_RDB_MANAGER_H -#define DISTRIBUTED_RDB_RDB_MANAGER_H +#ifndef FOUNDATION_BUNDLEMANAGER_BUNDLE_FRAMEWORK_INNERKITS_APPEXECFWK_BASE_INCLUDE_BUNDLE_COMMON_EVENT_H +#define FOUNDATION_BUNDLEMANAGER_BUNDLE_FRAMEWORK_INNERKITS_APPEXECFWK_BASE_INCLUDE_BUNDLE_COMMON_EVENT_H -#include #include -#include - -#include "rdb_service.h" -#include "rdb_types.h" - -namespace OHOS::DistributedRdb { -class RdbManager { -public: - static int GetRdbService(const RdbSyncerParam& param, std::shared_ptr &service); -}; -} // namespace OHOS::DistributedRdb -#endif + +namespace OHOS { +namespace AppExecFwk { +const std::string COMMON_EVENT_SANDBOX_PACKAGE_ADDED = "usual.event.SANDBOX_PACKAGE_ADDED"; + +const std::string COMMON_EVENT_SANDBOX_PACKAGE_REMOVED = "usual.event.SANDBOX_PACKAGE_REMOVED"; + +const std::string COMMON_EVENT_BUNDLE_SCAN_FINISHED = "usual.event.BUNDLE_SCAN_FINISHED"; + +const std::string OVERLAY_ADD_ACTION = "usual.event.OVERLAY_PACKAGE_ADDED"; + +const std::string OVERLAY_CHANGED_ACTION = "usual.event.OVERLAY_PACKAGE_CHANGED"; + +const std::string OVERLAY_STATE_CHANGED = "usual.event.OVERLAY_STATE_CHANGED"; +} // AppExecFwk +} // OHOS +#endif // FOUNDATION_BUNDLEMANAGER_BUNDLE_FRAMEWORK_INNERKITS_APPEXECFWK_BASE_INCLUDE_BUNDLE_COMMON_EVENT_H \ No newline at end of file diff --git a/mock/innerkits/bundle_framework/appexecfwk_base/include/bundle_info.h b/mock/innerkits/bundle_framework/appexecfwk_base/include/bundle_info.h index 80e9a745..2d271b3b 100644 --- a/mock/innerkits/bundle_framework/appexecfwk_base/include/bundle_info.h +++ b/mock/innerkits/bundle_framework/appexecfwk_base/include/bundle_info.h @@ -42,6 +42,18 @@ enum BundleFlag { GET_BUNDLE_WITH_HASH_VALUE = 0x00000030, }; +enum class GetBundleInfoFlag { + GET_BUNDLE_INFO_DEFAULT = 0x00000000, + GET_BUNDLE_INFO_WITH_APPLICATION = 0x00000001, + GET_BUNDLE_INFO_WITH_HAP_MODULE = 0x00000002, + GET_BUNDLE_INFO_WITH_ABILITY = 0x00000004, + GET_BUNDLE_INFO_WITH_EXTENSION_ABILITY = 0x00000008, + GET_BUNDLE_INFO_WITH_REQUESTED_PERMISSION = 0x00000010, + GET_BUNDLE_INFO_WITH_METADATA = 0x00000020, + GET_BUNDLE_INFO_WITH_DISABLE = 0x00000040, + GET_BUNDLE_INFO_WITH_SIGNATURE_INFO = 0x00000080, +}; + struct RequestPermissionUsedScene : public Parcelable { std::vector abilities; std::string when; @@ -61,6 +73,16 @@ struct RequestPermission : public Parcelable { virtual bool Marshalling(Parcel &parcel) const override; static RequestPermission *Unmarshalling(Parcel &parcel); }; + +struct SignatureInfo : public Parcelable { + std::string appId; + std::string fingerprint; + + bool ReadFromParcel(Parcel &parcel); + virtual bool Marshalling(Parcel &parcel) const override; + static SignatureInfo *Unmarshalling(Parcel &parcel); +}; + // configuration information about a bundle struct BundleInfo : public Parcelable { std::string name; @@ -83,7 +105,6 @@ struct BundleInfo : public Parcelable { std::string mainEntry; // modulePackage std::string entryModuleName; // moduleName bool entryInstallationFree = false; // application : false; atomic service : true - std::string appId; // user related fields, assign when calling the get interface @@ -91,6 +112,7 @@ struct BundleInfo : public Parcelable { int gid = -1; int64_t installTime = 0; int64_t updateTime = 0; + int32_t appIndex = 0; // index for sandbox app ApplicationInfo applicationInfo; std::vector abilityInfos; @@ -106,6 +128,7 @@ struct BundleInfo : public Parcelable { std::vector defPermissions; std::vector reqPermissionStates; std::vector reqPermissionDetails; + std::vector overlayBundleInfos; // unused std::string cpuAbi; @@ -116,6 +139,9 @@ struct BundleInfo : public Parcelable { int32_t minSdkVersion = -1; int32_t maxSdkVersion = -1; bool isDifferentName = false; + int32_t overlayType = NON_OVERLAY_TYPE; + + SignatureInfo signatureInfo; bool ReadFromParcel(Parcel &parcel); virtual bool Marshalling(Parcel &parcel) const override; diff --git a/mock/innerkits/bundle_framework/appexecfwk_core/include/bundlemgr/bundle_installer_interface.h b/mock/innerkits/bundle_framework/appexecfwk_core/include/bundlemgr/bundle_installer_interface.h index 9cb7729d..4b5e16be 100644 --- a/mock/innerkits/bundle_framework/appexecfwk_core/include/bundlemgr/bundle_installer_interface.h +++ b/mock/innerkits/bundle_framework/appexecfwk_core/include/bundlemgr/bundle_installer_interface.h @@ -123,6 +123,7 @@ public: INSTALL_MULTIPLE_HAPS, UNINSTALL, UNINSTALL_MODULE, + UNINSTALL_BY_UNINSTALL_PARAM, RECOVER, INSTALL_SANDBOX_APP, UNINSTALL_SANDBOX_APP, diff --git a/mock/innerkits/bundle_framework/appexecfwk_core/include/bundlemgr/bundle_mgr_interface.h b/mock/innerkits/bundle_framework/appexecfwk_core/include/bundlemgr/bundle_mgr_interface.h index ad77c945..ae07463c 100644 --- a/mock/innerkits/bundle_framework/appexecfwk_core/include/bundlemgr/bundle_mgr_interface.h +++ b/mock/innerkits/bundle_framework/appexecfwk_core/include/bundlemgr/bundle_mgr_interface.h @@ -981,11 +981,7 @@ public: GET_BUNDLE_ARCHIVE_INFO, GET_HAP_MODULE_INFO, GET_LAUNCH_WANT_FOR_BUNDLE, - CHECK_PUBLICKEYS, GET_PERMISSION_DEF, - HAS_SYSTEM_CAPABILITY, - GET_SYSTEM_AVAILABLE_CAPABILITIES, - IS_SAFE_MODE, CLEAN_BUNDLE_CACHE_FILES, CLEAN_BUNDLE_DATA_FILES, REGISTER_BUNDLE_STATUS_CALLBACK, @@ -998,8 +994,6 @@ public: SET_ABILITY_ENABLED, GET_ABILITY_INFO, GET_ABILITY_INFO_WITH_MODULE_NAME, - GET_ABILITY_PIXELMAP_ICON, - GET_ABILITY_PIXELMAP_ICON_WITH_MODULE_NAME, GET_ALL_FORMS_INFO, GET_FORMS_INFO_BY_APP, GET_FORMS_INFO_BY_MODULE, @@ -1023,7 +1017,6 @@ public: QUERY_EXTENSION_INFO, QUERY_EXTENSION_INFO_BY_TYPE, VERIFY_CALLING_PERMISSION, - GET_ACCESSIBLE_APP_CODE_PATH, QUERY_EXTENSION_ABILITY_INFO_BY_URI, IS_MODULE_REMOVABLE, SET_MODULE_REMOVABLE, @@ -1036,15 +1029,45 @@ public: IMPLICIT_QUERY_INFOS, GET_ALL_DEPENDENT_MODULE_NAMES, GET_SANDBOX_APP_BUNDLE_INFO, - SET_DISPOSED_STATUS, - GET_DISPOSED_STATUS, QUERY_CALLING_BUNDLE_NAME, GET_DEFAULT_APP_PROXY, GET_BUNDLE_STATS, CHECK_ABILITY_ENABLE_INSTALL, GET_SANDBOX_APP_ABILITY_INFO, GET_SANDBOX_APP_EXTENSION_INFOS, - GET_SANDBOX_MODULE_INFO + GET_SANDBOX_MODULE_INFO, + GET_MEDIA_DATA, + GET_QUICK_FIX_MANAGER_PROXY, + GET_STRING_BY_ID, + GET_ICON_BY_ID, + GET_UDID_BY_NETWORK_ID, + GET_APP_CONTROL_PROXY, + SET_DEBUG_MODE, + QUERY_ABILITY_INFOS_V9, + QUERY_EXTENSION_INFO_WITHOUT_TYPE_V9, + QUERY_EXTENSION_INFO_V9, + GET_APPLICATION_INFOS_WITH_INT_FLAGS_V9, + GET_APPLICATION_INFO_WITH_INT_FLAGS_V9, + GET_BUNDLE_ARCHIVE_INFO_WITH_INT_FLAGS_V9, + GET_BUNDLE_INFO_WITH_INT_FLAGS_V9, + GET_BUNDLE_INFOS_WITH_INT_FLAGS_V9, + GET_SHORTCUT_INFO_V9, + REGISTER_BUNDLE_EVENT_CALLBACK, + UNREGISTER_BUNDLE_EVENT_CALLBACK, + GET_BUNDLE_INFO_FOR_SELF, + VERIFY_SYSTEM_API, + GET_OVERLAY_MANAGER_PROXY, + SILENT_INSTALL, + PROCESS_PRELOAD, + GET_APP_PROVISION_INFO, + GET_PROVISION_METADATA, + GET_BASE_SHARED_BUNDLE_INFOS, + GET_ALL_SHARED_BUNDLE_INFO, + GET_SHARED_BUNDLE_INFO, + GET_SHARED_BUNDLE_INFO_BY_SELF, + GET_SHARED_DEPENDENCIES, + GET_DEPENDENT_BUNDLE_INFO, + GET_UID_BY_DEBUG_BUNDLE_NAME, }; }; } // namespace AppExecFwk diff --git a/mock/innerkits/bundle_framework/appexecfwk_core/include/bundlemgr/status_receiver_interface.h b/mock/innerkits/bundle_framework/appexecfwk_core/include/bundlemgr/status_receiver_interface.h index d01af230..fad959e0 100644 --- a/mock/innerkits/bundle_framework/appexecfwk_core/include/bundlemgr/status_receiver_interface.h +++ b/mock/innerkits/bundle_framework/appexecfwk_core/include/bundlemgr/status_receiver_interface.h @@ -86,6 +86,22 @@ public: ERR_INSTALL_TYPE_ERROR, ERR_INSTALL_SDK_INCOMPATIBLE, ERR_INSTALL_SO_INCOMPATIBLE, + ERR_INSTALL_AN_INCOMPATIBLE, + ERR_INSTALL_NOT_UNIQUE_DISTRO_MODULE_NAME, + ERR_INSTALL_INCONSISTENT_MODULE_NAME, + ERR_INSTALL_SINGLETON_INCOMPATIBLE, + ERR_INSTALL_DISALLOWED, + ERR_INSTALL_DEVICE_TYPE_NOT_SUPPORTED, + ERR_INSTALL_DEPENDENT_MODULE_NOT_EXIST, + ERR_INSTALL_ASAN_ENABLED_NOT_SAME, + ERR_INSTALL_ASAN_ENABLED_NOT_SUPPORT, + ERR_INSTALL_BUNDLE_TYPE_NOT_SAME, + ERR_INSTALL_SHARE_APP_LIBRARY_NOT_ALLOWED, + ERR_INSTALL_COMPATIBLE_POLICY_NOT_SAME, + ERR_APPEXECFWK_UNINSTALL_SHARE_APP_LIBRARY_IS_NOT_EXIST, + ERR_APPEXECFWK_UNINSTALL_SHARE_APP_LIBRARY_IS_RELIED, + ERR_APPEXECFWK_UNINSTALL_BUNDLE_IS_SHARED_LIBRARY, + ERR_INSTALL_FILE_IS_SHARED_LIBRARY, // signature errcode ERR_INSTALL_FAILED_INVALID_SIGNATURE_FILE_PATH, @@ -117,7 +133,10 @@ public: ERR_INSTALL_PARSE_PROFILE_MISSING_PROP, ERR_INSTALL_PARSE_PERMISSION_ERROR, ERR_INSTALL_PARSE_PROFILE_PROP_CHECK_ERROR, + ERR_INSTALL_PARSE_PROFILE_PROP_SIZE_CHECK_ERROR, ERR_INSTALL_PARSE_RPCID_FAILED, + ERR_INSTALL_PARSE_NATIVE_SO_FAILED, + ERR_INSTALL_PARSE_AN_FAILED, ERR_INSTALLD_PARAM_ERROR, ERR_INSTALLD_GET_PROXY_ERROR, @@ -128,6 +147,29 @@ public: ERR_INSTALLD_EXTRACT_FILES_FAILED, ERR_INSTALLD_RNAME_DIR_FAILED, ERR_INSTALLD_CLEAN_DIR_FAILED, + ERR_INSTALLD_PERMISSION_DENIED, + + // overlay installation + ERR_OVERLAY_INSTALLATION_FAILED_INTERNAL_ERROR, + ERR_OVERLAY_INSTALLATION_FAILED_INVALID_BUNDLE_NAME, + ERR_OVERLAY_INSTALLATION_FAILED_INVALID_MODULE_NAME, + ERR_OVERLAY_INSTALLATION_FAILED_ERROR_HAP_TYPE, + ERR_OVERLAY_INSTALLATION_FAILED_ERROR_BUNDLE_TYPE, + ERR_OVERLAY_INSTALLATION_FAILED_TARGET_BUNDLE_NAME_MISSED, + ERR_OVERLAY_INSTALLATION_FAILED_TARGET_MODULE_NAME_MISSED, + ERR_OVERLAY_INSTALLATION_FAILED_TARGET_BUNDLE_NAME_NOT_SAME, + ERR_OVERLAY_INSTALLATION_FAILED_INTERNAL_EXTERNAL_OVERLAY_EXISTED_SIMULTANEOUSLY, + ERR_OVERLAY_INSTALLATION_FAILED_TARGET_PRIORITY_NOT_SAME, + ERR_OVERLAY_INSTALLATION_FAILED_INVALID_PRIORITY, + ERR_OVERLAY_INSTALLATION_FAILED_INCONSISTENT_VERSION_CODE, + ERR_OVERLAY_INSTALLATION_FAILED_SERVICE_EXCEPTION, + ERR_OVERLAY_INSTALLATION_FAILED_BUNDLE_NAME_SAME_WITH_TARGET_BUNDLE_NAME, + ERR_OVERLAY_INSTALLATION_FAILED_NO_SYSTEM_APPLICATION_FOR_EXTERNAL_OVERLAY, + ERR_OVERLAY_INSTALLATION_FAILED_DIFFERENT_SIGNATURE_CERTIFICATE, + ERR_OVERLAY_INSTALLATION_FAILED_TARGET_BUNDLE_IS_OVERLAY_BUNDLE, + ERR_OVERLAY_INSTALLATION_FAILED_TARGET_MODULE_IS_OVERLAY_MODULE, + ERR_OVERLAY_INSTALLATION_FAILED_OVERLAY_TYPE_NOT_SAME, + ERR_OVERLAY_INSTALLATION_FAILED_INVALID_BUNDLE_DIR, ERR_UNINSTALL_SYSTEM_APP_ERROR, ERR_UNINSTALL_KILLING_APP_ERROR, @@ -137,6 +179,7 @@ public: ERR_UNINSTALL_BUNDLE_MGR_SERVICE_ERROR, ERR_UNINSTALL_MISSING_INSTALLED_BUNDLE, ERR_UNINSTALL_MISSING_INSTALLED_MODULE, + ERR_UNINSTALL_DISALLOWED, ERR_UNKNOWN, ERR_FAILED_GET_INSTALLER_PROXY, @@ -145,10 +188,11 @@ public: ERR_RECOVER_GET_BUNDLEPATH_ERROR = 201, ERR_RECOVER_INVALID_BUNDLE_NAME, + ERR_RECOVER_NOT_ALLOWED, ERR_USER_NOT_EXIST = 301, - ERR_USER_CREATE_FALIED, - ERR_USER_REMOVE_FALIED, + ERR_USER_CREATE_FAILED, + ERR_USER_REMOVE_FAILED, ERR_USER_NOT_INSTALL_HAP, }; }; diff --git a/mock/innerkits/device_manager/devicemanagersdk/include/device_manager.h b/mock/innerkits/device_manager/devicemanagersdk/include/device_manager.h index ffccadc0..ddd92e92 100644 --- a/mock/innerkits/device_manager/devicemanagersdk/include/device_manager.h +++ b/mock/innerkits/device_manager/devicemanagersdk/include/device_manager.h @@ -1,17 +1,17 @@ /* - * 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. - */ +* Copyright (c) 2022-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_DEVICE_MANAGER_H #define OHOS_DEVICE_MANAGER_H @@ -29,189 +29,229 @@ namespace OHOS { namespace DistributedHardware { class DeviceManager { public: - static DeviceManager &GetInstance(); + static DeviceManager &GetInstance(); public: - /** - * @tc.name: DeviceManagerImpl::InitDeviceManager - * @tc.desc: Initialize DeviceManager - * @tc.type: FUNC - */ - virtual int32_t InitDeviceManager(const std::string &pkgName, std::shared_ptr dmInitCallback) = 0; - /** - * @tc.name: DeviceManagerImpl::UnInitDeviceManager - * @tc.desc: UnInitialize DeviceManager - * @tc.type: FUNC - */ - virtual int32_t UnInitDeviceManager(const std::string &pkgName) = 0; - /** - * @tc.name: DeviceManagerImpl::GetTrustedDeviceList - * @tc.desc: Get device list of trusted devices - * @tc.type: FUNC - */ - virtual int32_t GetTrustedDeviceList(const std::string &pkgName, const std::string &extra, - std::vector &deviceList) = 0; - /** - * @tc.name: DeviceManagerImpl::GetLocalDeviceInfo - * @tc.desc: Get local device information - * @tc.type: FUNC - */ - virtual int32_t GetLocalDeviceInfo(const std::string &pkgName, DmDeviceInfo &deviceInfo) = 0; - /** - * @brief Register device status callback - * @param pkgName package name - * @param extra extra info.This parameter can be null. - * @param callback device state callback - * @return return 0 if success - */ - virtual int32_t RegisterDevStateCallback(const std::string &pkgName, const std::string &extra, - std::shared_ptr callback) = 0; - /** - * @brief Unregister device status callback - * @param pkgName package name - * @return return 0 if success - */ - virtual int32_t UnRegisterDevStateCallback(const std::string &pkgName) = 0; - /** - * @tc.name: DeviceManagerImpl::StartDeviceDiscovery - * @tc.desc: Initiate device discovery - * @tc.type: FUNC - */ - virtual int32_t StartDeviceDiscovery(const std::string &pkgName, const DmSubscribeInfo &subscribeInfo, - const std::string &extra, std::shared_ptr callback) = 0; - /** - * @tc.name: DeviceManagerImpl::StopDeviceDiscovery - * @tc.desc: Stop device discovery - * @tc.type: FUNC - */ - virtual int32_t StopDeviceDiscovery(const std::string &pkgName, uint16_t subscribeId) = 0; - /** - * @tc.name: DeviceManagerImpl::PublishDeviceDiscovery - * @tc.desc: Publish device discovery - * @tc.type: FUNC - */ - virtual int32_t PublishDeviceDiscovery(const std::string &pkgName, const DmPublishInfo &publishInfo, - std::shared_ptr callback) = 0; - /** - * @tc.name: DeviceManagerImpl::UnPublishDeviceDiscovery - * @tc.desc: UnPublish device discovery - * @tc.type: FUNC - */ - virtual int32_t UnPublishDeviceDiscovery(const std::string &pkgName, int32_t publishId) = 0; - /** - * @tc.name: DeviceManagerImpl::AuthenticateDevice - * @tc.desc: Complete verifying the device - * @tc.type: FUNC - */ - virtual int32_t AuthenticateDevice(const std::string &pkgName, int32_t authType, const DmDeviceInfo &deviceInfo, - const std::string &extra, std::shared_ptr callback) = 0; - /** - * @tc.name: DeviceManagerImpl::UnAuthenticateDevice - * @tc.desc: Cancel complete verification of device - * @tc.type: FUNC - */ - virtual int32_t UnAuthenticateDevice(const std::string &pkgName, const DmDeviceInfo &deviceInfo) = 0; - /** - * @tc.name: DeviceManagerImpl::VerifyAuthentication - * @tc.desc: Verify device authentication - * @tc.type: FUNC - */ - virtual int32_t VerifyAuthentication(const std::string &pkgName, const std::string &authPara, - std::shared_ptr callback) = 0; - /** - * @tc.name: DeviceManagerImpl::RegisterDeviceManagerFaCallback - * @tc.desc: Register Fa callback for device manager - * @tc.type: FUNC - */ - virtual int32_t RegisterDeviceManagerFaCallback(const std::string &pkgName, - std::shared_ptr callback) = 0; - /** - * @tc.name: DeviceManagerImpl::UnRegisterDeviceManagerFaCallback - * @tc.desc: Unregister Fa callback for device manager - * @tc.type: FUNC - */ - virtual int32_t UnRegisterDeviceManagerFaCallback(const std::string &pkgName) = 0; - /** - * @tc.name: DeviceManagerImpl::GetFaParam - * @tc.desc: Get Fa Param - * @tc.type: FUNC - */ - virtual int32_t GetFaParam(const std::string &pkgName, DmAuthParam &faParam) = 0; - /** - * @tc.name: DeviceManagerImpl::SetUserOperation - * @tc.desc: Set User Actions - * @tc.type: FUNC - */ - virtual int32_t SetUserOperation(const std::string &pkgName, int32_t action) = 0; - /** - * @tc.name: DeviceManagerImpl::GetUdidByNetworkId - * @tc.desc: Get Udid by NetworkId - * @tc.type: FUNC - */ - virtual int32_t GetUdidByNetworkId(const std::string &pkgName, const std::string &netWorkId, std::string &udid) = 0; - /** - * @tc.name: DeviceManagerImpl::GetUuidByNetworkId - * @tc.desc: Get Uuid by NetworkId - * @tc.type: FUNC - */ - virtual int32_t GetUuidByNetworkId(const std::string &pkgName, const std::string &netWorkId, std::string &uuid) = 0; - /** - * @brief Unregister device status callback - * @param pkgName package name - * @param extra extra info.This parameter can be null. - * @return return 0 if success - */ - virtual int32_t RegisterDevStateCallback(const std::string &pkgName, const std::string &extra) = 0; - /** - * @brief Unregister device status callback - * @param pkgName package name - * @param extra extra info.This parameter can be null. - * @return return 0 if success - */ - virtual int32_t UnRegisterDevStateCallback(const std::string &pkgName, const std::string &extra) = 0; - /** - * @tc.name: DeviceManagerImpl::RequestCredential - * @tc.desc: RequestCredential - * @tc.type: FUNC - */ - virtual int32_t RequestCredential(const std::string &pkgName, const std::string &reqJsonStr, - std::string &returnJsonStr) = 0; - /** - * @tc.name: DeviceManagerImpl::ImportCredential - * @tc.desc: ImportCredential - * @tc.type: FUNC - */ - virtual int32_t ImportCredential(const std::string &pkgName, const std::string &credentialInfo) = 0; - /** - * @tc.name: DeviceManagerImpl::DeleteCredential - * @tc.desc: DeleteCredential - * @tc.type: FUNC - */ - virtual int32_t DeleteCredential(const std::string &pkgName, const std::string &deleteInfo) = 0; - /** - * @tc.name: DeviceManagerImpl::RegisterCredentialCallback - * @tc.desc: RegisterCredentialCallback - * @tc.type: FUNC - */ - virtual int32_t RegisterCredentialCallback(const std::string &pkgName, - std::shared_ptr callback) = 0; - /** - * @tc.name: DeviceManagerImpl::UnRegisterCredentialCallback - * @tc.desc: UnRegisterCredentialCallback - * @tc.type: FUNC - */ - virtual int32_t UnRegisterCredentialCallback(const std::string &pkgName) = 0; - /** - * @brief Notify Event to DM - * @param pkgName package name - * @param event event info - */ - virtual int32_t NotifyEvent(const std::string &pkgName, const int32_t eventId, const std::string &event) = 0; + /** + * @brief Initialize DeviceManager. + * @param pkgName package name. + * @param dmInitCallback the callback to be invoked upon InitDeviceManager. + * @return Returns 0 if success. + */ + virtual int32_t InitDeviceManager(const std::string &pkgName, std::shared_ptr dmInitCallback) = 0; + /** + * @brief UnInitialize DeviceManager. + * @param pkgName package name. + * @return Returns 0 if success. + */ + virtual int32_t UnInitDeviceManager(const std::string &pkgName) = 0; + /** + * @brief Get device info list of trusted devices. + * @param pkgName package name. + * @param extra extra info.This parameter can be null. + * @param deviceList device info list. + * @return Returns a list of trusted devices. + */ + virtual int32_t GetTrustedDeviceList(const std::string &pkgName, const std::string &extra, + std::vector &deviceList) = 0; + /** + * @brief Get local device information. + * @param pkgName package name. + * @param deviceInfo device info. + * @return Returns local device info. + */ + virtual int32_t GetLocalDeviceInfo(const std::string &pkgName, DmDeviceInfo &deviceInfo) = 0; + /** + * @tc.name: DeviceManagerImpl::GetDeviceInfo + * @tc.desc: Get local device information by networkId + * @tc.type: FUNC + */ + virtual int32_t GetDeviceInfo(const std::string &pkgName, const std::string networkId, + DmDeviceInfo &deviceInfo) = 0; + /** + * @brief Register device status callback. + * @param pkgName package name. + * @param extra extra info.This parameter can be null. + * @param callback device state callback. + * @return Returns 0 if success. + */ + virtual int32_t RegisterDevStateCallback(const std::string &pkgName, const std::string &extra, + std::shared_ptr callback) = 0; + /** + * @brief Unregister device status callback. + * @param pkgName package name. + * @return Returns 0 if success. + */ + virtual int32_t UnRegisterDevStateCallback(const std::string &pkgName) = 0; + /** + * @brief Initiate device discovery. + * @param pkgName package name. + * @param subscribeInfo subscribe info to discovery device. + * @param extra extra info.This parameter can be null. + * @param callback discovery callback. + * @return Returns 0 if success. + */ + virtual int32_t StartDeviceDiscovery(const std::string &pkgName, const DmSubscribeInfo &subscribeInfo, + const std::string &extra, std::shared_ptr callback) = 0; + /** + * @brief Stop device discovery. + * @param pkgName package name. + * @param subscribeInfo subscribe info to discovery device. + * @return Returns 0 if success. + */ + virtual int32_t StopDeviceDiscovery(const std::string &pkgName, uint16_t subscribeId) = 0; + /** + * @brief Publish device discovery. + * @param pkgName package name. + * @param publishInfo publish info to Publish discovery device. + * @param callback the callback to be invoked upon PublishDeviceDiscovery. + * @return Returns 0 if success. + */ + virtual int32_t PublishDeviceDiscovery(const std::string &pkgName, const DmPublishInfo &publishInfo, + std::shared_ptr callback) = 0; + /** + * @brief UnPublish device discovery. + * @param pkgName package name. + * @param publishId service publish ID, identify a publish operation, should be a unique id in package range. + * @return Returns 0 if success. + */ + virtual int32_t UnPublishDeviceDiscovery(const std::string &pkgName, int32_t publishId) = 0; + /** + * @brief Authenticate the specified device. + * @param pkgName package name. + * @param authType authType of device to authenticate. + * @param deviceInfo deviceInfo of device to authenticate. + * @param extra extra info.This parameter can be null. + * @param callback the callback to be invoked upon AuthenticateDevice. + * @return Returns 0 if success. + */ + virtual int32_t AuthenticateDevice(const std::string &pkgName, int32_t authType, const DmDeviceInfo &deviceInfo, + const std::string &extra, std::shared_ptr callback) = 0; + /** + * @brief Cancel complete verification of device. + * @param pkgName package name. + * @param deviceInfo deviceInfo of device to authenticate. + * @return Returns 0 if success. + */ + virtual int32_t UnAuthenticateDevice(const std::string &pkgName, const DmDeviceInfo &deviceInfo) = 0; + /** + * @brief Verify device authentication. + * @param pkgName package name. + * @param authPara authPara of device to authenticate. + * @param callback the callback to be invoked upon VerifyAuthentication. + * @return Returns 0 if success. + */ + virtual int32_t VerifyAuthentication(const std::string &pkgName, const std::string &authPara, + std::shared_ptr callback) = 0; + /** + * @brief Get Fa Param. + * @param pkgName package name. + * @param faParam fa param. + * @return Returns 0 if success. + */ + virtual int32_t GetFaParam(const std::string &pkgName, DmAuthParam &faParam) = 0; + /** + * @brief Set User Actions. + * @param pkgName package name. + * @param action user operation action. + * @param params indicates the input param of the user. + * @return Returns 0 if success. + */ + virtual int32_t SetUserOperation(const std::string &pkgName, int32_t action, const std::string ¶ms) = 0; + /** + * @brief Get Udid by NetworkId. + * @param pkgName package name. + * @param netWorkId netWork Id. + * @param udid unique device id. + * @return Returns 0 if success. + */ + virtual int32_t GetUdidByNetworkId(const std::string &pkgName, const std::string &netWorkId, std::string &udid) = 0; + /** + * @brief Get Uuid by NetworkId. + * @param pkgName package name. + * @param netWorkId netWork Id. + * @param uuid universally unique id. + * @return Returns 0 if success. + */ + virtual int32_t GetUuidByNetworkId(const std::string &pkgName, const std::string &netWorkId, std::string &uuid) = 0; + /** + * @brief Unregister device status callback. + * @param pkgName package name. + * @param extra extra info.This parameter can be null. + * @return Returns 0 if success. + */ + virtual int32_t RegisterDevStateCallback(const std::string &pkgName, const std::string &extra) = 0; + /** + * @brief Unregister device status callback. + * @param pkgName package name. + * @param extra extra info.This parameter can be null. + * @return Returns 0 if success. + */ + virtual int32_t UnRegisterDevStateCallback(const std::string &pkgName, const std::string &extra) = 0; + /** + * @brief Request credential information. + * @param pkgName package name. + * @param reqJsonStr request credential params, the params is json string, it includes version and userId. + * @param returnJsonStr return json string, it includes deviceId, devicePk, useId and version. + * @return Returns 0 if success. + */ + virtual int32_t RequestCredential(const std::string &pkgName, const std::string &reqJsonStr, + std::string &returnJsonStr) = 0; + /** + * @brief Import credential information. + * @param pkgName package name. + * @param credentialInfo import credential params, the params is json string, it includes processType, authType, + * userId, deviceId, version, devicePk and credentialData, the credentialData is array, each array element + * includes credentialType, credentialId, serverPk, pkInfoSignature, pkInfo, authCode, peerDeviceId. + * @return Returns 0 if success. + */ + virtual int32_t ImportCredential(const std::string &pkgName, const std::string &credentialInfo) = 0; + /** + * @brief Delete credential information. + * @param pkgName package name. + * @param deleteInfo delete credential params. the params is json string, it includes processType, authType, userId. + * @return Returns 0 if success. + */ + virtual int32_t DeleteCredential(const std::string &pkgName, const std::string &deleteInfo) = 0; + /** + * @brief Register credential callback. + * @param pkgName package name. + * @param callback credential callback. + * @return Returns 0 if success. + */ + virtual int32_t RegisterCredentialCallback(const std::string &pkgName, + std::shared_ptr callback) = 0; + /** + * @brief UnRegister credential callback. + * @param pkgName package name. + * @return Returns 0 if success. + */ + virtual int32_t UnRegisterCredentialCallback(const std::string &pkgName) = 0; + /** + * @brief Notify event to device manager. + * @param pkgName package name. + * @param event event info. + * @param event event string. + * @return Returns 0 if success. + */ + virtual int32_t NotifyEvent(const std::string &pkgName, const int32_t eventId, const std::string &event) = 0; - virtual int GetEncryptedUuidByNetworkId(const std::string &pkgName, const std::string &networkId, - std::string &uuid) = 0; - virtual int GenerateEncryptedUuid(const std::string &pkgName, const std::string &uuid, const std::string &appId, - std::string &encryptedUuid) = 0; + /** + * @brief Get encrypted uuid. + * @param networkId device networkId. + * @return Returns encrypted uuid. + */ + virtual int32_t GetEncryptedUuidByNetworkId(const std::string &pkgName, const std::string &networkId, + std::string &uuid) = 0; + + /** + * @brief Get encrypted uuid. + * @param uuid device uuid. + * @param tokenId tokenId. + * @return Returns encrypted uuid. + */ + virtual int32_t GenerateEncryptedUuid(const std::string &pkgName, const std::string &uuid, const std::string &appId, + std::string &encryptedUuid) = 0; }; } // namespace DistributedHardware } // namespace OHOS diff --git a/mock/innerkits/device_manager/devicemanagersdk/include/device_manager_impl.h b/mock/innerkits/device_manager/devicemanagersdk/include/device_manager_impl.h index 068ddf0b..4215fde3 100644 --- a/mock/innerkits/device_manager/devicemanagersdk/include/device_manager_impl.h +++ b/mock/innerkits/device_manager/devicemanagersdk/include/device_manager_impl.h @@ -112,31 +112,13 @@ public: */ virtual int32_t VerifyAuthentication(const std::string &pkgName, const std::string &authPara, std::shared_ptr callback) override; - /** - * @tc.name: DeviceManagerImpl::RegisterDeviceManagerFaCallback - * @tc.desc: Register Fa callback for device manager - * @tc.type: FUNC - */ - virtual int32_t RegisterDeviceManagerFaCallback(const std::string &packageName, - std::shared_ptr callback) override; - /** - * @tc.name: DeviceManagerImpl::UnRegisterDeviceManagerFaCallback - * @tc.desc: Unregister Fa callback for device manager - * @tc.type: FUNC - */ - virtual int32_t UnRegisterDeviceManagerFaCallback(const std::string &pkgName) override; /** * @tc.name: DeviceManagerImpl::GetFaParam * @tc.desc: Get Fa Param * @tc.type: FUNC */ virtual int32_t GetFaParam(const std::string &pkgName, DmAuthParam &faParam) override; - /** - * @tc.name: DeviceManagerImpl::SetUserOperation - * @tc.desc: Set User Actions - * @tc.type: FUNC - */ - virtual int32_t SetUserOperation(const std::string &pkgName, int32_t action) override; + /** * @tc.name: DeviceManagerImpl::GetUdidByNetworkId * @tc.desc: Get Udid by NetworkId @@ -203,10 +185,14 @@ public: */ virtual int32_t NotifyEvent(const std::string &pkgName, const int32_t eventId, const std::string &event) override; - int GetEncryptedUuidByNetworkId(const std::string &pkgName, const std::string &networkId, + virtual int32_t GetEncryptedUuidByNetworkId(const std::string &pkgName, const std::string &networkId, std::string &uuid) override; - int GenerateEncryptedUuid(const std::string &pkgName, const std::string &uuid, const std::string &appId, - std::string &encryptedUuid) override; + + virtual int32_t GenerateEncryptedUuid(const std::string &pkgName, const std::string &uuid, + const std::string &appId, std::string &encryptedUuid) override; + + int32_t GetDeviceInfo(const std::string &pkgName, const std::string networkId, DmDeviceInfo &deviceInfo) override; + int32_t SetUserOperation(const std::string &pkgName, int32_t action, const std::string ¶ms) override; private: DeviceManagerImpl() = default; diff --git a/mock/innerkits/huks/libhukssdk/include/hks_log.h b/mock/innerkits/huks/libhukssdk/include/hks_log.h index 3a5a31a4..ed971a70 100644 --- a/mock/innerkits/huks/libhukssdk/include/hks_log.h +++ b/mock/innerkits/huks/libhukssdk/include/hks_log.h @@ -1,17 +1,17 @@ /* - * 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. - */ +* 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 HKS_LOG_H #define HKS_LOG_H @@ -47,13 +47,13 @@ #endif #define HKS_LOG_I(fmt, arg...) HILOG_INFO(LOG_ENGINE, "%" LOG_PUBLIC "s[%" LOG_PUBLIC "u]: " fmt "\n", \ - __func__, __LINE__, ##arg) + __func__, __LINE__, ##arg) #define HKS_LOG_W(fmt, arg...) HILOG_WARN(LOG_ENGINE, "%" LOG_PUBLIC "s[%" LOG_PUBLIC "u]: " fmt "\n", \ - __func__, __LINE__, ##arg) + __func__, __LINE__, ##arg) #define HKS_LOG_E(fmt, arg...) HILOG_ERROR(LOG_ENGINE, "%" LOG_PUBLIC "s[%" LOG_PUBLIC "u]: " fmt "\n", \ - __func__, __LINE__, ##arg) + __func__, __LINE__, ##arg) #define HKS_LOG_D(fmt, arg...) HILOG_DEBUG(LOG_ENGINE, "%" LOG_PUBLIC "s[%" LOG_PUBLIC "u]: " fmt "\n", \ - __func__, __LINE__, ##arg) + __func__, __LINE__, ##arg) #else #define HKS_LOG_I(...) #define HKS_LOG_W(...) diff --git a/mock/innerkits/huks/libhukssdk/include/hks_template.h b/mock/innerkits/huks/libhukssdk/include/hks_template.h index 20eca013..a6a7f2a8 100644 --- a/mock/innerkits/huks/libhukssdk/include/hks_template.h +++ b/mock/innerkits/huks/libhukssdk/include/hks_template.h @@ -1,8 +1,75 @@ -// -// Created by HuTao on 2023/2/20. -// +/* +* 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 LDBPROJ_HKS_TEMPLATE_H -#define LDBPROJ_HKS_TEMPLATE_H +#ifndef HKS_TEMPLATE_H +#define HKS_TEMPLATE_H -#endif //LDBPROJ_HKS_TEMPLATE_H +#undef HKS_NULL_POINTER + +#ifdef __cplusplus +#define HKS_NULL_POINTER nullptr +#else +#define HKS_NULL_POINTER NULL +#endif + +#define HKS_IF_NOT_SUCC_LOGE_RETURN(RESULT, ERROR_CODE, LOG_MESSAGE, ...) \ +if ((RESULT) != HKS_SUCCESS) { \ + HKS_LOG_E(LOG_MESSAGE, ##__VA_ARGS__); \ + return (ERROR_CODE); \ +} + +#define HKS_IF_NOT_SUCC_LOGE_BREAK(RESULT, LOG_MESSAGE, ...) \ +if ((RESULT) != HKS_SUCCESS) { \ + HKS_LOG_E(LOG_MESSAGE, ##__VA_ARGS__); \ + break; \ +} + +#define HKS_IF_NOT_SUCC_BREAK(RESULT, ...) \ +if ((RESULT) != HKS_SUCCESS) { \ + break; \ +} + +#define HKS_IF_NOT_SUCC_LOGE(RESULT, LOG_MESSAGE, ...) \ +if ((RESULT) != HKS_SUCCESS) { \ + HKS_LOG_E(LOG_MESSAGE, ##__VA_ARGS__); \ +} + +#define HKS_IF_NOT_SUCC_RETURN(RESULT, ERROR_CODE) \ +if ((RESULT) != HKS_SUCCESS) { \ + return (ERROR_CODE); \ +} + +#define HKS_IF_NULL_LOGE_RETURN(OBJECT, ERROR_CODE, LOG_MESSAGE, ...) \ +if ((OBJECT) == HKS_NULL_POINTER) { \ + HKS_LOG_E(LOG_MESSAGE, ##__VA_ARGS__); \ + return (ERROR_CODE); \ +} + +#define HKS_IF_NULL_LOGE_BREAK(OBJECT, LOG_MESSAGE, ...) \ +if ((OBJECT) == HKS_NULL_POINTER) { \ + HKS_LOG_E(LOG_MESSAGE, ##__VA_ARGS__); \ + break; \ +} + +#define HKS_IF_NULL_RETURN(OBJECT, ERROR_CODE) \ +if ((OBJECT) == HKS_NULL_POINTER) { \ + return (ERROR_CODE); \ +} + +#define HKS_IF_NULL_BREAK(OBJECT) \ +if ((OBJECT) == HKS_NULL_POINTER) { \ + break; \ +} +#endif /* HKS_TEMPLATE_H */ diff --git a/mock/innerkits/huks/libhukssdk/include/hks_type.h b/mock/innerkits/huks/libhukssdk/include/hks_type.h index 6b674e24..4dfaa437 100644 --- a/mock/innerkits/huks/libhukssdk/include/hks_type.h +++ b/mock/innerkits/huks/libhukssdk/include/hks_type.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2021-2022 Huawei Device Co., Ltd. +* Copyright (c) 2021-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 @@ -13,6 +13,14 @@ * limitations under the License. */ +/** +* @file hks_param.h +* +* @brief Declares huks struct and enum. +* +* @since 8 +*/ + #ifndef HKS_TYPE_H #define HKS_TYPE_H @@ -70,6 +78,12 @@ extern "C" { #define HKS_CERT_DEVICE_SIZE 2048 #define HKS_CERT_APP_SIZE 4096 +#define HKS_KEY_BLOB_AT_KEY_SIZE 256 +#define HKS_KEY_BLOB_AT_KEY_BYTES 32 + +/** +* @brief hks key type +*/ enum HksKeyType { HKS_KEY_TYPE_RSA_PUBLIC_KEY = 0x01001000, HKS_KEY_TYPE_RSA_KEYPAIR = 0x01002000, @@ -95,6 +109,9 @@ enum HksKeyType { HKS_KEY_TYPE_PBKDF2 = 0x07000000, }; +/** +* @brief hks key purpose +*/ enum HksKeyPurpose { HKS_KEY_PURPOSE_ENCRYPT = 1, /* Usable with RSA, EC, AES, and SM4 keys. */ HKS_KEY_PURPOSE_DECRYPT = 2, /* Usable with RSA, EC, AES, and SM4 keys. */ @@ -107,6 +124,9 @@ enum HksKeyPurpose { HKS_KEY_PURPOSE_AGREE = 256, /* Usable with agree. */ }; +/** +* @brief hks key digest +*/ enum HksKeyDigest { HKS_DIGEST_NONE = 0, HKS_DIGEST_MD5 = 1, @@ -118,6 +138,9 @@ enum HksKeyDigest { HKS_DIGEST_SHA512 = 14, }; +/** +* @brief hks key padding +*/ enum HksKeyPadding { HKS_PADDING_NONE = 0, HKS_PADDING_OAEP = 1, @@ -127,6 +150,9 @@ enum HksKeyPadding { HKS_PADDING_PKCS7 = 5, }; +/** +* @brief hks cipher mode +*/ enum HksCipherMode { HKS_MODE_ECB = 1, HKS_MODE_CBC = 2, @@ -136,6 +162,9 @@ enum HksCipherMode { HKS_MODE_GCM = 32, }; +/** +* @brief hks key size +*/ enum HksKeySize { HKS_RSA_KEY_SIZE_512 = 512, HKS_RSA_KEY_SIZE_768 = 768, @@ -164,6 +193,9 @@ enum HksKeySize { HKS_SM4_KEY_SIZE_128 = 128, }; +/** +* @brief hks key algorithm +*/ enum HksKeyAlg { HKS_ALG_RSA = 1, HKS_ALG_ECC = 2, @@ -173,6 +205,7 @@ enum HksKeyAlg { HKS_ALG_HMAC = 50, HKS_ALG_HKDF = 51, HKS_ALG_PBKDF2 = 52, + HKS_ALG_GMKDF = 53, HKS_ALG_ECDH = 100, HKS_ALG_X25519 = 101, @@ -184,6 +217,9 @@ enum HksKeyAlg { HKS_ALG_SM4 = 152, }; +/** +* @brief hks algorithm suite +*/ enum HuksAlgSuite { /* Algorithm suites of unwrapping wrapped-key by huks */ /* Unwrap suite of key agreement type */ @@ -204,14 +240,37 @@ enum HuksAlgSuite { * | key_material_size_len (4 Byte) | key_material_size | key_mat_enc_length (4 Byte) | key_mat_enc_data */ HKS_UNWRAP_SUITE_ECDH_AES_256_GCM_NOPADDING = 2, + + /* WrappedData format(Bytes Array): + * | SM2_plain_pubkey_length (4 Byte) | SM2_plain_pubkey | signData_size_length (4 Byte) | signData_size + * | kek_enc_data_length (4 Byte) | kek_enc_data | kek_material_size_len(4 Byte) | kek_material_size + * | factor1_data_len (4 Byte) | factor1_data | factor2_data_len (4 Byte) | factor2_data + * | mac_data_length (4 Byte) | mac_data | key_mat_enc_length (4 Byte) | key_mat_enc_data + * | iv_data_length (4 Byte) | iv_data |key_material_size_len (4 Byte) | key_material_size + */ + HKS_UNWRAP_SUITE_SM2_SM4_128_CBC_PKCS7_WITH_VERIFY_DIG_SM3 = 3, + + /* WrappedData format(Bytes Array): + * | kek_enc_data_length (4 Byte) | kek_enc_data | kek_material_size_len(4 Byte) | kek_material_size + * | factor1_data_len (4 Byte) | factor1_data | factor2_data_len (4 Byte) | factor2_data + * | mac_data_length (4 Byte) | mac_data | key_mat_enc_length (4 Byte) | key_mat_enc_data + * | iv_data_length (4 Byte) | iv_data |key_material_size_len (4 Byte) | key_material_size + */ + HKS_UNWRAP_SUITE_SM2_SM4_128_CBC_PKCS7 = 4, }; +/** +* @brief hks key generate type +*/ enum HksKeyGenerateType { HKS_KEY_GENERATE_TYPE_DEFAULT = 0, HKS_KEY_GENERATE_TYPE_DERIVE = 1, HKS_KEY_GENERATE_TYPE_AGREE = 2, }; +/** +* @brief hks key flag +*/ enum HksKeyFlag { HKS_KEY_FLAG_IMPORT_KEY = 1, HKS_KEY_FLAG_GENERATE_KEY = 2, @@ -219,17 +278,36 @@ enum HksKeyFlag { HKS_KEY_FLAG_DERIVE_KEY = 4, }; +/** +* @brief hks key storage type +*/ enum HksKeyStorageType { HKS_STORAGE_TEMP = 0, HKS_STORAGE_PERSISTENT = 1, + HKS_STORAGE_ONLY_USED_IN_HUKS = 2, + HKS_STORAGE_ALLOW_KEY_EXPORTED = 3, }; +/** +* @brief hks import key type +*/ enum HksImportKeyType { HKS_KEY_TYPE_PUBLIC_KEY = 0, HKS_KEY_TYPE_PRIVATE_KEY = 1, HKS_KEY_TYPE_KEY_PAIR = 2, }; +/** +* @brief hks rsa pss salt len type +*/ +enum HksRsaPssSaltLenType { + HKS_RSA_PSS_SALTLEN_DIGEST = 0, /* Salt length matches digest */ + HKS_RSA_PSS_SALTLEN_MAX = 1, /* Set salt length to maximum possible, default type */ +}; + +/** +* @brief hks error code +*/ enum HksErrorCode { HKS_SUCCESS = 0, HKS_FAILURE = -1, @@ -327,6 +405,9 @@ enum HksErrorCode { HKS_ERROR_UNKNOWN_ERROR = -1000, }; +/** +* @brief hks err code +*/ enum HksErrCode { HUKS_ERR_CODE_PERMISSION_FAIL = 201, HUKS_ERR_CODE_ILLEGAL_ARGUMENT = 401, @@ -349,6 +430,9 @@ enum HksErrCode { HUKS_ERR_CODE_CALL_SERVICE_FAILED = 12000015, }; +/** +* @brief hks tag type +*/ enum HksTagType { HKS_TAG_TYPE_INVALID = 0 << 28, HKS_TAG_TYPE_INT = 1 << 28, @@ -358,28 +442,43 @@ enum HksTagType { HKS_TAG_TYPE_BYTES = 5 << 28, }; +/** +* @brief hks send type +*/ enum HksSendType { HKS_SEND_TYPE_ASYNC = 0, HKS_SEND_TYPE_SYNC, }; +/** +* @brief hks user auth type +*/ enum HksUserAuthType { HKS_USER_AUTH_TYPE_FINGERPRINT = 1 << 0, HKS_USER_AUTH_TYPE_FACE = 1 << 1, HKS_USER_AUTH_TYPE_PIN = 1 << 2, }; +/** +* @brief hks auth access type +*/ enum HksAuthAccessType { HKS_AUTH_ACCESS_INVALID_CLEAR_PASSWORD = 1 << 0, HKS_AUTH_ACCESS_INVALID_NEW_BIO_ENROLL = 1 << 1, }; +/** +* @brief hks challenge type +*/ enum HksChallengeType { HKS_CHALLENGE_TYPE_NORMAL = 0, HKS_CHALLENGE_TYPE_CUSTOM = 1, HKS_CHALLENGE_TYPE_NONE = 2, }; +/** +* @brief hks challenge position +*/ enum HksChallengePosition { HKS_CHALLENGE_POS_0 = 0, HKS_CHALLENGE_POS_1, @@ -387,154 +486,157 @@ enum HksChallengePosition { HKS_CHALLENGE_POS_3, }; +/** +* @brief hks secure sign type +*/ enum HksSecureSignType { HKS_SECURE_SIGN_WITH_AUTHINFO = 1, }; +#define HKS_ASSIGN_ENUM_VALUE(x, y) x = y, + +#define HKS_ASSIGN_PARAM_ALG_ENUM \ + HKS_ASSIGN_ENUM_VALUE(HKS_TAG_INVALID, HKS_TAG_TYPE_INVALID | 0) \ + /* Base algrithom TAG: 1 - 200 */\ + HKS_ASSIGN_ENUM_VALUE(HKS_TAG_ALGORITHM, HKS_TAG_TYPE_UINT | 1) \ + HKS_ASSIGN_ENUM_VALUE(HKS_TAG_PURPOSE, HKS_TAG_TYPE_UINT | 2) \ + HKS_ASSIGN_ENUM_VALUE(HKS_TAG_KEY_SIZE, HKS_TAG_TYPE_UINT | 3) \ + HKS_ASSIGN_ENUM_VALUE(HKS_TAG_DIGEST, HKS_TAG_TYPE_UINT | 4) \ + HKS_ASSIGN_ENUM_VALUE(HKS_TAG_PADDING, HKS_TAG_TYPE_UINT | 5) \ + HKS_ASSIGN_ENUM_VALUE(HKS_TAG_BLOCK_MODE, HKS_TAG_TYPE_UINT | 6) \ + HKS_ASSIGN_ENUM_VALUE(HKS_TAG_KEY_TYPE, HKS_TAG_TYPE_UINT | 7) \ + HKS_ASSIGN_ENUM_VALUE(HKS_TAG_ASSOCIATED_DATA, HKS_TAG_TYPE_BYTES | 8) \ + HKS_ASSIGN_ENUM_VALUE(HKS_TAG_NONCE, HKS_TAG_TYPE_BYTES | 9) \ + HKS_ASSIGN_ENUM_VALUE(HKS_TAG_IV, HKS_TAG_TYPE_BYTES | 10) \ + /* Key derivation TAG */\ + HKS_ASSIGN_ENUM_VALUE(HKS_TAG_INFO, HKS_TAG_TYPE_BYTES | 11) \ + HKS_ASSIGN_ENUM_VALUE(HKS_TAG_SALT, HKS_TAG_TYPE_BYTES | 12) \ + HKS_ASSIGN_ENUM_VALUE(HKS_TAG_PWD, HKS_TAG_TYPE_BYTES | 13) \ + HKS_ASSIGN_ENUM_VALUE(HKS_TAG_ITERATION, HKS_TAG_TYPE_UINT | 14) \ + HKS_ASSIGN_ENUM_VALUE(HKS_TAG_KEY_GENERATE_TYPE, HKS_TAG_TYPE_UINT | 15) /* choose from enum HksKeyGenerateType */\ + HKS_ASSIGN_ENUM_VALUE(HKS_TAG_DERIVE_MAIN_KEY, HKS_TAG_TYPE_BYTES | 16) \ + HKS_ASSIGN_ENUM_VALUE(HKS_TAG_DERIVE_FACTOR, HKS_TAG_TYPE_BYTES | 17) \ + HKS_ASSIGN_ENUM_VALUE(HKS_TAG_DERIVE_ALG, HKS_TAG_TYPE_UINT | 18) \ + HKS_ASSIGN_ENUM_VALUE(HKS_TAG_AGREE_ALG, HKS_TAG_TYPE_UINT | 19) \ + HKS_ASSIGN_ENUM_VALUE(HKS_TAG_AGREE_PUBLIC_KEY_IS_KEY_ALIAS, HKS_TAG_TYPE_BOOL | 20) \ + HKS_ASSIGN_ENUM_VALUE(HKS_TAG_AGREE_PRIVATE_KEY_ALIAS, HKS_TAG_TYPE_BYTES | 21) \ + HKS_ASSIGN_ENUM_VALUE(HKS_TAG_AGREE_PUBLIC_KEY, HKS_TAG_TYPE_BYTES | 22) \ + HKS_ASSIGN_ENUM_VALUE(HKS_TAG_KEY_ALIAS, HKS_TAG_TYPE_BYTES | 23) \ + HKS_ASSIGN_ENUM_VALUE(HKS_TAG_DERIVE_KEY_SIZE, HKS_TAG_TYPE_UINT | 24) \ + HKS_ASSIGN_ENUM_VALUE(HKS_TAG_IMPORT_KEY_TYPE, HKS_TAG_TYPE_UINT | 25) /* choose from enum HksImportKeyType */\ + HKS_ASSIGN_ENUM_VALUE(HKS_TAG_UNWRAP_ALGORITHM_SUITE, HKS_TAG_TYPE_UINT | 26) \ + HKS_ASSIGN_ENUM_VALUE(HKS_TAG_CIPHER_TEXT, HKS_TAG_TYPE_BYTES | 27) \ + /* parameters required by HuksCoreChipsetPlatformDecrypt */\ + HKS_ASSIGN_ENUM_VALUE(HKS_TAG_PEER_PUBLIC_KEY, HKS_TAG_TYPE_BYTES | 28) \ + HKS_ASSIGN_ENUM_VALUE(HKS_TAG_DERIVE_AGREE_KEY_STORAGE_FLAG, HKS_TAG_TYPE_UINT | 29) \ + HKS_ASSIGN_ENUM_VALUE(HKS_TAG_RSA_PSS_SALT_LEN_TYPE, HKS_TAG_TYPE_UINT | 30) /* only supported for PSS padding */\ + /* Key authentication related TAG: 201 - 300 */\ + HKS_ASSIGN_ENUM_VALUE(HKS_TAG_ACTIVE_DATETIME, HKS_TAG_TYPE_ULONG | 201) \ + /* Date when new "messages" should not be created. */\ + HKS_ASSIGN_ENUM_VALUE(HKS_TAG_ORIGINATION_EXPIRE_DATETIME, HKS_TAG_TYPE_ULONG | 202) \ + /* Date when existing "messages" should not be used. */\ + HKS_ASSIGN_ENUM_VALUE(HKS_TAG_USAGE_EXPIRE_DATETIME, HKS_TAG_TYPE_ULONG | 203) \ + /* Key creation time */\ + HKS_ASSIGN_ENUM_VALUE(HKS_TAG_CREATION_DATETIME, HKS_TAG_TYPE_ULONG | 204) \ + /* Other authentication related TAG: 301 - 500 */\ + HKS_ASSIGN_ENUM_VALUE(HKS_TAG_ALL_USERS, HKS_TAG_TYPE_BOOL | 301) \ + HKS_ASSIGN_ENUM_VALUE(HKS_TAG_USER_ID, HKS_TAG_TYPE_UINT | 302) \ + HKS_ASSIGN_ENUM_VALUE(HKS_TAG_NO_AUTH_REQUIRED, HKS_TAG_TYPE_BOOL | 303) \ + HKS_ASSIGN_ENUM_VALUE(HKS_TAG_USER_AUTH_TYPE, HKS_TAG_TYPE_UINT | 304) \ + HKS_ASSIGN_ENUM_VALUE(HKS_TAG_AUTH_TIMEOUT, HKS_TAG_TYPE_UINT | 305) \ + HKS_ASSIGN_ENUM_VALUE(HKS_TAG_AUTH_TOKEN, HKS_TAG_TYPE_BYTES | 306) \ + /* Key secure access control and user auth TAG */\ + HKS_ASSIGN_ENUM_VALUE(HKS_TAG_KEY_AUTH_ACCESS_TYPE, HKS_TAG_TYPE_UINT | 307) \ + HKS_ASSIGN_ENUM_VALUE(HKS_TAG_KEY_SECURE_SIGN_TYPE, HKS_TAG_TYPE_UINT | 308) \ + HKS_ASSIGN_ENUM_VALUE(HKS_TAG_CHALLENGE_TYPE, HKS_TAG_TYPE_UINT | 309) \ + HKS_ASSIGN_ENUM_VALUE(HKS_TAG_CHALLENGE_POS, HKS_TAG_TYPE_UINT | 310) \ + HKS_ASSIGN_ENUM_VALUE(HKS_TAG_KEY_AUTH_PURPOSE, HKS_TAG_TYPE_UINT | 311) \ + /* Attestation related TAG: 501 - 600 */\ + HKS_ASSIGN_ENUM_VALUE(HKS_TAG_ATTESTATION_CHALLENGE, HKS_TAG_TYPE_BYTES | 501) \ + HKS_ASSIGN_ENUM_VALUE(HKS_TAG_ATTESTATION_APPLICATION_ID, HKS_TAG_TYPE_BYTES | 502) \ + HKS_ASSIGN_ENUM_VALUE(HKS_TAG_ATTESTATION_ID_BRAND, HKS_TAG_TYPE_BYTES | 503) \ + HKS_ASSIGN_ENUM_VALUE(HKS_TAG_ATTESTATION_ID_DEVICE, HKS_TAG_TYPE_BYTES | 504) \ + HKS_ASSIGN_ENUM_VALUE(HKS_TAG_ATTESTATION_ID_PRODUCT, HKS_TAG_TYPE_BYTES | 505) \ + HKS_ASSIGN_ENUM_VALUE(HKS_TAG_ATTESTATION_ID_SERIAL, HKS_TAG_TYPE_BYTES | 506) \ + HKS_ASSIGN_ENUM_VALUE(HKS_TAG_ATTESTATION_ID_IMEI, HKS_TAG_TYPE_BYTES | 507) \ + HKS_ASSIGN_ENUM_VALUE(HKS_TAG_ATTESTATION_ID_MEID, HKS_TAG_TYPE_BYTES | 508) \ + HKS_ASSIGN_ENUM_VALUE(HKS_TAG_ATTESTATION_ID_MANUFACTURER, HKS_TAG_TYPE_BYTES | 509) \ + HKS_ASSIGN_ENUM_VALUE(HKS_TAG_ATTESTATION_ID_MODEL, HKS_TAG_TYPE_BYTES | 510) \ + HKS_ASSIGN_ENUM_VALUE(HKS_TAG_ATTESTATION_ID_ALIAS, HKS_TAG_TYPE_BYTES | 511) \ + HKS_ASSIGN_ENUM_VALUE(HKS_TAG_ATTESTATION_ID_SOCID, HKS_TAG_TYPE_BYTES | 512) \ + HKS_ASSIGN_ENUM_VALUE(HKS_TAG_ATTESTATION_ID_UDID, HKS_TAG_TYPE_BYTES | 513) \ + HKS_ASSIGN_ENUM_VALUE(HKS_TAG_ATTESTATION_ID_SEC_LEVEL_INFO, HKS_TAG_TYPE_BYTES | 514) \ + HKS_ASSIGN_ENUM_VALUE(HKS_TAG_ATTESTATION_ID_VERSION_INFO, HKS_TAG_TYPE_BYTES | 515) \ + HKS_ASSIGN_ENUM_VALUE(HKS_TAG_ATTESTATION_BASE64, HKS_TAG_TYPE_BOOL | 516) \ + /* Extention TAG: 1001 - 9999 */\ + HKS_ASSIGN_ENUM_VALUE(HKS_TAG_IS_KEY_ALIAS, HKS_TAG_TYPE_BOOL | 1001) \ + HKS_ASSIGN_ENUM_VALUE(HKS_TAG_KEY_STORAGE_FLAG, HKS_TAG_TYPE_UINT | 1002) /* choose from enum HksKeyStorageType */\ + HKS_ASSIGN_ENUM_VALUE(HKS_TAG_IS_ALLOWED_WRAP, HKS_TAG_TYPE_BOOL | 1003) \ + HKS_ASSIGN_ENUM_VALUE(HKS_TAG_KEY_WRAP_TYPE, HKS_TAG_TYPE_UINT | 1004) \ + HKS_ASSIGN_ENUM_VALUE(HKS_TAG_KEY_AUTH_ID, HKS_TAG_TYPE_BYTES | 1005) \ + HKS_ASSIGN_ENUM_VALUE(HKS_TAG_KEY_ROLE, HKS_TAG_TYPE_UINT | 1006) \ + HKS_ASSIGN_ENUM_VALUE(HKS_TAG_KEY_FLAG, HKS_TAG_TYPE_UINT | 1007) /* choose from enum HksKeyFlag */\ + HKS_ASSIGN_ENUM_VALUE(HKS_TAG_IS_ASYNCHRONIZED, HKS_TAG_TYPE_UINT | 1008) \ + HKS_ASSIGN_ENUM_VALUE(HKS_TAG_SECURE_KEY_ALIAS, HKS_TAG_TYPE_BOOL | 1009) \ + HKS_ASSIGN_ENUM_VALUE(HKS_TAG_SECURE_KEY_UUID, HKS_TAG_TYPE_BYTES | 1010) \ + HKS_ASSIGN_ENUM_VALUE(HKS_TAG_KEY_DOMAIN, HKS_TAG_TYPE_UINT | 1011) \ + /* Inner-use TAG: 10001 - 10999 */\ + HKS_ASSIGN_ENUM_VALUE(HKS_TAG_PACKAGE_NAME, HKS_TAG_TYPE_BYTES | 10002) \ + HKS_ASSIGN_ENUM_VALUE(HKS_TAG_ACCESS_TIME, HKS_TAG_TYPE_UINT | 10003) \ + HKS_ASSIGN_ENUM_VALUE(HKS_TAG_USES_TIME, HKS_TAG_TYPE_UINT | 10004) \ + HKS_ASSIGN_ENUM_VALUE(HKS_TAG_CRYPTO_CTX, HKS_TAG_TYPE_ULONG | 10005) \ + HKS_ASSIGN_ENUM_VALUE(HKS_TAG_PAYLOAD_LEN, HKS_TAG_TYPE_UINT | 10008) \ + HKS_ASSIGN_ENUM_VALUE(HKS_TAG_AE_TAG, HKS_TAG_TYPE_BYTES | 10009) \ + HKS_ASSIGN_ENUM_VALUE(HKS_TAG_IS_KEY_HANDLE, HKS_TAG_TYPE_ULONG | 10010) \ + HKS_ASSIGN_ENUM_VALUE(HKS_TAG_KEY_INIT_CHALLENGE, HKS_TAG_TYPE_BYTES | 10011) \ + HKS_ASSIGN_ENUM_VALUE(HKS_TAG_IS_USER_AUTH_ACCESS, HKS_TAG_TYPE_BOOL | 10012) \ + HKS_ASSIGN_ENUM_VALUE(HKS_TAG_USER_AUTH_CHALLENGE, HKS_TAG_TYPE_BYTES | 10013) \ + HKS_ASSIGN_ENUM_VALUE(HKS_TAG_USER_AUTH_ENROLL_ID_INFO, HKS_TAG_TYPE_BYTES | 10014) \ + HKS_ASSIGN_ENUM_VALUE(HKS_TAG_USER_AUTH_SECURE_UID, HKS_TAG_TYPE_BYTES | 10015) \ + HKS_ASSIGN_ENUM_VALUE(HKS_TAG_KEY_AUTH_RESULT, HKS_TAG_TYPE_INT | 10016) \ + HKS_ASSIGN_ENUM_VALUE(HKS_TAG_IF_NEED_APPEND_AUTH_INFO, HKS_TAG_TYPE_BOOL | 10017) \ + HKS_ASSIGN_ENUM_VALUE(HKS_TAG_VERIFIED_AUTH_TOKEN, HKS_TAG_TYPE_BYTES | 10018) \ + HKS_ASSIGN_ENUM_VALUE(HKS_TAG_IS_APPEND_UPDATE_DATA, HKS_TAG_TYPE_BOOL | 10019) \ + HKS_ASSIGN_ENUM_VALUE(HKS_TAG_KEY_ACCESS_TIME, HKS_TAG_TYPE_ULONG | 10020) \ + /* TAGs used for paramSetOut */\ + HKS_ASSIGN_ENUM_VALUE(HKS_TAG_SYMMETRIC_KEY_DATA, HKS_TAG_TYPE_BYTES | 20001) \ + HKS_ASSIGN_ENUM_VALUE(HKS_TAG_ASYMMETRIC_PUBLIC_KEY_DATA, HKS_TAG_TYPE_BYTES | 20002) \ + HKS_ASSIGN_ENUM_VALUE(HKS_TAG_ASYMMETRIC_PRIVATE_KEY_DATA, HKS_TAG_TYPE_BYTES | 20003) \ + +#define HKS_ASSIGN_PARAM_FILE_ENUM \ + HKS_ASSIGN_ENUM_VALUE(HKS_TAG_PROCESS_NAME, HKS_TAG_TYPE_BYTES | 10001) \ + HKS_ASSIGN_ENUM_VALUE(HKS_TAG_KEY, HKS_TAG_TYPE_BYTES | 10006) \ + HKS_ASSIGN_ENUM_VALUE(HKS_TAG_KEY_VERSION, HKS_TAG_TYPE_UINT | 10007) \ + /* Os version related TAG */\ + HKS_ASSIGN_ENUM_VALUE(HKS_TAG_OS_VERSION, HKS_TAG_TYPE_UINT | 10101) \ + HKS_ASSIGN_ENUM_VALUE(HKS_TAG_OS_PATCHLEVEL, HKS_TAG_TYPE_UINT | 10102) \ + +/** +* @brief hks Tag +*/ enum HksTag { - /* Invalid TAG */ - HKS_TAG_INVALID = HKS_TAG_TYPE_INVALID | 0, - - /* Base algrithom TAG: 1 - 200 */ - HKS_TAG_ALGORITHM = HKS_TAG_TYPE_UINT | 1, - HKS_TAG_PURPOSE = HKS_TAG_TYPE_UINT | 2, - HKS_TAG_KEY_SIZE = HKS_TAG_TYPE_UINT | 3, - HKS_TAG_DIGEST = HKS_TAG_TYPE_UINT | 4, - HKS_TAG_PADDING = HKS_TAG_TYPE_UINT | 5, - HKS_TAG_BLOCK_MODE = HKS_TAG_TYPE_UINT | 6, - HKS_TAG_KEY_TYPE = HKS_TAG_TYPE_UINT | 7, - HKS_TAG_ASSOCIATED_DATA = HKS_TAG_TYPE_BYTES | 8, - HKS_TAG_NONCE = HKS_TAG_TYPE_BYTES | 9, - HKS_TAG_IV = HKS_TAG_TYPE_BYTES | 10, - - /* Key derivation TAG */ - HKS_TAG_INFO = HKS_TAG_TYPE_BYTES | 11, - HKS_TAG_SALT = HKS_TAG_TYPE_BYTES | 12, - HKS_TAG_PWD = HKS_TAG_TYPE_BYTES | 13, - HKS_TAG_ITERATION = HKS_TAG_TYPE_UINT | 14, - - HKS_TAG_KEY_GENERATE_TYPE = HKS_TAG_TYPE_UINT | 15, /* choose from enum HksKeyGenerateType */ - HKS_TAG_DERIVE_MAIN_KEY = HKS_TAG_TYPE_BYTES | 16, - HKS_TAG_DERIVE_FACTOR = HKS_TAG_TYPE_BYTES | 17, - HKS_TAG_DERIVE_ALG = HKS_TAG_TYPE_UINT | 18, - HKS_TAG_AGREE_ALG = HKS_TAG_TYPE_UINT | 19, - HKS_TAG_AGREE_PUBLIC_KEY_IS_KEY_ALIAS = HKS_TAG_TYPE_BOOL | 20, - HKS_TAG_AGREE_PRIVATE_KEY_ALIAS = HKS_TAG_TYPE_BYTES | 21, - HKS_TAG_AGREE_PUBLIC_KEY = HKS_TAG_TYPE_BYTES | 22, - HKS_TAG_KEY_ALIAS = HKS_TAG_TYPE_BYTES | 23, - HKS_TAG_DERIVE_KEY_SIZE = HKS_TAG_TYPE_UINT | 24, - HKS_TAG_IMPORT_KEY_TYPE = HKS_TAG_TYPE_UINT | 25, /* choose from enum HksImportKeyType */ - HKS_TAG_UNWRAP_ALGORITHM_SUITE = HKS_TAG_TYPE_UINT | 26, - - /* - * Key authentication related TAG: 201 - 300 - * - * Start of validity + /** + * HUKS tags for alg enum */ - HKS_TAG_ACTIVE_DATETIME = HKS_TAG_TYPE_ULONG | 201, - - /* Date when new "messages" should not be created. */ - HKS_TAG_ORIGINATION_EXPIRE_DATETIME = HKS_TAG_TYPE_ULONG | 202, - - /* Date when existing "messages" should not be used. */ - HKS_TAG_USAGE_EXPIRE_DATETIME = HKS_TAG_TYPE_ULONG | 203, - - /* Key creation time */ - HKS_TAG_CREATION_DATETIME = HKS_TAG_TYPE_ULONG | 204, + HKS_ASSIGN_PARAM_ALG_ENUM - /* Other authentication related TAG: 301 - 500 */ - HKS_TAG_ALL_USERS = HKS_TAG_TYPE_BOOL | 301, - HKS_TAG_USER_ID = HKS_TAG_TYPE_UINT | 302, - HKS_TAG_NO_AUTH_REQUIRED = HKS_TAG_TYPE_BOOL | 303, - HKS_TAG_USER_AUTH_TYPE = HKS_TAG_TYPE_UINT | 304, - HKS_TAG_AUTH_TIMEOUT = HKS_TAG_TYPE_UINT | 305, - HKS_TAG_AUTH_TOKEN = HKS_TAG_TYPE_BYTES | 306, - - /* - * Key secure access control and user auth TAG - */ - HKS_TAG_KEY_AUTH_ACCESS_TYPE = HKS_TAG_TYPE_UINT | 307, - HKS_TAG_KEY_SECURE_SIGN_TYPE = HKS_TAG_TYPE_UINT | 308, - HKS_TAG_CHALLENGE_TYPE = HKS_TAG_TYPE_UINT | 309, - HKS_TAG_CHALLENGE_POS = HKS_TAG_TYPE_UINT | 310, - - /* Attestation related TAG: 501 - 600 */ - HKS_TAG_ATTESTATION_CHALLENGE = HKS_TAG_TYPE_BYTES | 501, - HKS_TAG_ATTESTATION_APPLICATION_ID = HKS_TAG_TYPE_BYTES | 502, - HKS_TAG_ATTESTATION_ID_BRAND = HKS_TAG_TYPE_BYTES | 503, - HKS_TAG_ATTESTATION_ID_DEVICE = HKS_TAG_TYPE_BYTES | 504, - HKS_TAG_ATTESTATION_ID_PRODUCT = HKS_TAG_TYPE_BYTES | 505, - HKS_TAG_ATTESTATION_ID_SERIAL = HKS_TAG_TYPE_BYTES | 506, - HKS_TAG_ATTESTATION_ID_IMEI = HKS_TAG_TYPE_BYTES | 507, - HKS_TAG_ATTESTATION_ID_MEID = HKS_TAG_TYPE_BYTES | 508, - HKS_TAG_ATTESTATION_ID_MANUFACTURER = HKS_TAG_TYPE_BYTES | 509, - HKS_TAG_ATTESTATION_ID_MODEL = HKS_TAG_TYPE_BYTES | 510, - HKS_TAG_ATTESTATION_ID_ALIAS = HKS_TAG_TYPE_BYTES | 511, - HKS_TAG_ATTESTATION_ID_SOCID = HKS_TAG_TYPE_BYTES | 512, - HKS_TAG_ATTESTATION_ID_UDID = HKS_TAG_TYPE_BYTES | 513, - HKS_TAG_ATTESTATION_ID_SEC_LEVEL_INFO = HKS_TAG_TYPE_BYTES | 514, - HKS_TAG_ATTESTATION_ID_VERSION_INFO = HKS_TAG_TYPE_BYTES | 515, - HKS_TAG_ATTESTATION_BASE64 = HKS_TAG_TYPE_BOOL | 516, - - /* - * Other reserved TAG: 601 - 1000 - * - * Extention TAG: 1001 - 9999 - */ - HKS_TAG_IS_KEY_ALIAS = HKS_TAG_TYPE_BOOL | 1001, - HKS_TAG_KEY_STORAGE_FLAG = HKS_TAG_TYPE_UINT | 1002, /* choose from enum HksKeyStorageType */ - HKS_TAG_IS_ALLOWED_WRAP = HKS_TAG_TYPE_BOOL | 1003, - HKS_TAG_KEY_WRAP_TYPE = HKS_TAG_TYPE_UINT | 1004, - HKS_TAG_KEY_AUTH_ID = HKS_TAG_TYPE_BYTES | 1005, - HKS_TAG_KEY_ROLE = HKS_TAG_TYPE_UINT | 1006, - HKS_TAG_KEY_FLAG = HKS_TAG_TYPE_UINT | 1007, /* choose from enum HksKeyFlag */ - HKS_TAG_IS_ASYNCHRONIZED = HKS_TAG_TYPE_UINT | 1008, - HKS_TAG_SECURE_KEY_ALIAS = HKS_TAG_TYPE_BOOL | 1009, - HKS_TAG_SECURE_KEY_UUID = HKS_TAG_TYPE_BYTES | 1010, - HKS_TAG_KEY_DOMAIN = HKS_TAG_TYPE_UINT | 1011, - - /* Inner-use TAG: 10001 - 10999 */ - HKS_TAG_PROCESS_NAME = HKS_TAG_TYPE_BYTES | 10001, - HKS_TAG_PACKAGE_NAME = HKS_TAG_TYPE_BYTES | 10002, - HKS_TAG_ACCESS_TIME = HKS_TAG_TYPE_UINT | 10003, - HKS_TAG_USES_TIME = HKS_TAG_TYPE_UINT | 10004, - HKS_TAG_CRYPTO_CTX = HKS_TAG_TYPE_ULONG | 10005, - HKS_TAG_KEY = HKS_TAG_TYPE_BYTES | 10006, - HKS_TAG_KEY_VERSION = HKS_TAG_TYPE_UINT | 10007, - HKS_TAG_PAYLOAD_LEN = HKS_TAG_TYPE_UINT | 10008, - HKS_TAG_AE_TAG = HKS_TAG_TYPE_BYTES | 10009, - HKS_TAG_IS_KEY_HANDLE = HKS_TAG_TYPE_ULONG | 10010, - HKS_TAG_KEY_INIT_CHALLENGE = HKS_TAG_TYPE_BYTES | 10011, - HKS_TAG_IS_USER_AUTH_ACCESS = HKS_TAG_TYPE_BOOL | 10012, - HKS_TAG_USER_AUTH_CHALLENGE = HKS_TAG_TYPE_BYTES | 10013, - HKS_TAG_USER_AUTH_ENROLL_ID_INFO = HKS_TAG_TYPE_BYTES | 10014, - HKS_TAG_USER_AUTH_SECURE_UID = HKS_TAG_TYPE_BYTES | 10015, - HKS_TAG_KEY_AUTH_RESULT = HKS_TAG_TYPE_INT | 10016, - HKS_TAG_IF_NEED_APPEND_AUTH_INFO = HKS_TAG_TYPE_BOOL | 10017, - HKS_TAG_VERIFIED_AUTH_TOKEN = HKS_TAG_TYPE_BYTES | 10018, - HKS_TAG_IS_APPEND_UPDATE_DATA = HKS_TAG_TYPE_BOOL | 10019, - HKS_TAG_KEY_ACCESS_TIME = HKS_TAG_TYPE_ULONG | 10020, - - /* Os version related TAG */ - HKS_TAG_OS_VERSION = HKS_TAG_TYPE_UINT | 10101, - HKS_TAG_OS_PATCHLEVEL = HKS_TAG_TYPE_UINT | 10102, - - /* - * Reversed TAGs for SOTER: 11000 - 12000 - * - * Other TAGs: 20001 - N - * TAGs used for paramSetOut + /** + * HUKS tags for key file enum */ - HKS_TAG_SYMMETRIC_KEY_DATA = HKS_TAG_TYPE_BYTES | 20001, - HKS_TAG_ASYMMETRIC_PUBLIC_KEY_DATA = HKS_TAG_TYPE_BYTES | 20002, - HKS_TAG_ASYMMETRIC_PRIVATE_KEY_DATA = HKS_TAG_TYPE_BYTES | 20003, + HKS_ASSIGN_PARAM_FILE_ENUM }; +/** +* @brief hks blob +*/ struct HksBlob { uint32_t size; uint8_t *data; }; +/** +* @brief hks param +*/ struct HksParam { uint32_t tag; union { @@ -546,22 +648,34 @@ struct HksParam { }; }; +/** +* @brief hks param set +*/ struct HksParamSet { uint32_t paramSetSize; uint32_t paramsCnt; struct HksParam params[]; }; +/** +* @brief hks certificate chain +*/ struct HksCertChain { struct HksBlob *certs; uint32_t certsCount; }; +/** +* @brief hks key info +*/ struct HksKeyInfo { struct HksBlob alias; struct HksParamSet *paramSet; }; +/** +* @brief hks public key info +*/ struct HksPubKeyInfo { enum HksKeyAlg keyAlg; uint32_t keySize; @@ -570,6 +684,9 @@ struct HksPubKeyInfo { uint32_t placeHolder; }; +/** +* @brief hks rsa key material +*/ struct HksKeyMaterialRsa { enum HksKeyAlg keyAlg; uint32_t keySize; @@ -578,6 +695,9 @@ struct HksKeyMaterialRsa { uint32_t dSize; }; +/** +* @brief hks ecc key material +*/ struct HksKeyMaterialEcc { enum HksKeyAlg keyAlg; uint32_t keySize; @@ -586,6 +706,9 @@ struct HksKeyMaterialEcc { uint32_t zSize; }; +/** +* @brief hks dsa key material +*/ struct HksKeyMaterialDsa { enum HksKeyAlg keyAlg; uint32_t keySize; @@ -596,6 +719,9 @@ struct HksKeyMaterialDsa { uint32_t gSize; }; +/** +* @brief hks dh key material +*/ struct HksKeyMaterialDh { enum HksKeyAlg keyAlg; uint32_t keySize; @@ -604,6 +730,9 @@ struct HksKeyMaterialDh { uint32_t reserved; }; +/** +* @brief hks 25519 key material +*/ struct HksKeyMaterial25519 { enum HksKeyAlg keyAlg; uint32_t keySize; @@ -612,20 +741,51 @@ struct HksKeyMaterial25519 { uint32_t reserved; }; -typedef struct __attribute__((__packed__)) HksUserAuthToken { - uint32_t version; +/** +* @brief hks user auth token plaintext data +*/ +typedef struct HksPlaintextData { uint8_t challenge[TOKEN_SIZE]; - uint64_t secureUid; - uint64_t enrolledId; - uint64_t credentialId; uint64_t time; uint32_t authTrustLevel; uint32_t authType; uint32_t authMode; uint32_t securityLevel; +} __attribute__((__packed__)) HksPlaintextData; + +/** +* @brief hks user auth token ciphertext data +*/ +typedef struct HksCiphertextData { + int32_t userId; + uint64_t secureUid; + uint64_t enrolledId; + uint64_t credentialId; +} __attribute__((__packed__)) HksCiphertextData; + +/** +* @brief hks user auth token +*/ +typedef struct __attribute__((__packed__)) HksUserAuthToken { + uint32_t version; + HksPlaintextData plaintextData; + HksCiphertextData ciphertextData; + uint8_t tag[HKS_AE_TAG_LEN]; + uint8_t iv[HKS_AE_NONCE_LEN]; uint8_t sign[SHA256_SIGN_LEN]; } __attribute__((__packed__)) HksUserAuthToken; +/** +* @brief hks user auth token key +*/ +struct HksAuthTokenKey { + uint8_t macKey[HKS_KEY_BLOB_AT_KEY_BYTES]; + uint8_t cipherKey[HKS_KEY_BLOB_AT_KEY_BYTES]; +}; + +/** +* @brief hks secure sign auth info +*/ typedef struct __attribute__((__packed__)) HksSecureSignAuthInfo { uint32_t userAuthType; uint64_t authenticatorId; @@ -640,6 +800,9 @@ typedef struct __attribute__((__packed__)) HksSecureSignAuthInfo { #define HKS_MAX_KEY_LEN (HKS_KEY_BYTES(HKS_RSA_KEY_SIZE_4096) * HKS_KEY_MATERIAL_NUM) #define HKS_MAX_KEY_MATERIAL_LEN (sizeof(struct HksPubKeyInfo) + HKS_MAX_KEY_LEN + HKS_AE_TAG_LEN) +/** +* @brief hks store header info +*/ struct HksStoreHeaderInfo { uint16_t version; uint16_t keyCount; @@ -649,6 +812,9 @@ struct HksStoreHeaderInfo { uint8_t hmac[HKS_HMAC_DIGEST_SHA512_LEN]; }; +/** +* @brief hks store key info +*/ struct HksStoreKeyInfo { uint16_t keyInfoLen; /* current keyinfo len */ uint16_t keySize; /* keySize of key from crypto hal after encrypted */ @@ -667,6 +833,9 @@ struct HksStoreKeyInfo { uint8_t authIdSize; }; +/** +* @brief hks 25519 key pair +*/ struct Hks25519KeyPair { uint32_t publicBufferSize; uint32_t privateBufferSize; @@ -690,6 +859,13 @@ static inline int32_t CheckBlob(const struct HksBlob *blob) return HKS_SUCCESS; } +/** +* @brief hks chipset platform decrypt scene +*/ +enum HksChipsetPlatformDecryptScene { + HKS_CHIPSET_PLATFORM_DECRYPT_SCENE_TA_TO_TA = 1, +}; + #ifdef __cplusplus } #endif diff --git a/mock/innerkits/ipc/ipc_core/include/ipc_object_proxy.h b/mock/innerkits/ipc/ipc_core/include/ipc_object_proxy.h index cf2ca652..3754d9b0 100644 --- a/mock/innerkits/ipc/ipc_core/include/ipc_object_proxy.h +++ b/mock/innerkits/ipc/ipc_core/include/ipc_object_proxy.h @@ -35,8 +35,6 @@ public: return true; }; - bool IsObjectDead() const; - int32_t GetObjectRefCount() override; int Dump(int fd, const std::vector &args) override; @@ -66,18 +64,18 @@ public: int InvokeListenThread(MessageParcel &data, MessageParcel &reply); int32_t NoticeServiceDie(); - std::string GetPidAndUidInfo(); - - std::string GetDataBusName(); - std::string TransDataBusName(uint32_t uid, uint32_t pid); + int GetPidUid(MessageParcel &reply); + std::string GetSessionName(); + std::string GetSessionNameForPidUid(uint32_t uid, uint32_t pid); + std::string GetGrantedSessionName(); int GetProto() const; void WaitForInit(); - std::u16string GetInterfaceDescriptor(); private: void MarkObjectDied(); int SendLocalRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &optionoption); int SendRequestInner(bool isLocal, uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option); + void ClearDeathRecipients(); #ifndef CONFIG_IPC_SINGLE void SetProto(int proto); @@ -88,7 +86,7 @@ private: int32_t IncRefToRemote(); - int GetSessionFromDBinderService(); + int GetProtoInfo(); bool AddDbinderDeathRecipient(); diff --git a/mock/innerkits/ipc/ipc_core/include/ipc_object_stub.h b/mock/innerkits/ipc/ipc_core/include/ipc_object_stub.h index 61ecd9aa..a3f677ce 100644 --- a/mock/innerkits/ipc/ipc_core/include/ipc_object_stub.h +++ b/mock/innerkits/ipc/ipc_core/include/ipc_object_stub.h @@ -64,8 +64,12 @@ public: uint32_t GetCallingTokenID(); + uint64_t GetCallingFullTokenID(); + uint32_t GetFirstTokenID(); + uint64_t GetFirstFullTokenID(); + virtual int OnRemoteDump(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option); virtual int32_t ProcessProto(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option); @@ -76,16 +80,15 @@ public: int32_t InvokerThread(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option); int32_t NoticeServiceDie(MessageParcel &data, MessageParcel &reply, MessageOption &option); int32_t InvokerDataBusThread(MessageParcel &data, MessageParcel &reply); - int32_t IncStubRefs(MessageParcel &data, MessageParcel &reply); - int32_t DecStubRefs(MessageParcel &data, MessageParcel &reply); int32_t AddAuthInfo(MessageParcel &data, MessageParcel &reply, uint32_t code); private: - int32_t GrantDataBusName(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option); - int32_t TransDataBusName(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option); - std::string CreateDatabusName(int uid, int pid); - std::string GetDataBusName(); - bool IsSamgrCall(uint32_t accessToken); + int GetPidUid(MessageParcel &data, MessageParcel &reply); + std::string GetSessionName(); + int32_t GetSessionNameForPidUid(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option); + int32_t GetGrantedSessionName(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option); + std::string CreateSessionName(int uid, int pid); + bool IsSamgrCall(); #endif private: bool IsDeviceIdIllegal(const std::string &deviceID); diff --git a/mock/innerkits/ipc/ipc_core/include/ipc_skeleton.h b/mock/innerkits/ipc/ipc_core/include/ipc_skeleton.h index 4ea3c1a3..822b457d 100644 --- a/mock/innerkits/ipc/ipc_core/include/ipc_skeleton.h +++ b/mock/innerkits/ipc/ipc_core/include/ipc_skeleton.h @@ -39,8 +39,14 @@ public: static uint32_t GetCallingTokenID(); + static uint64_t GetCallingFullTokenID(); + static uint32_t GetFirstTokenID(); + static uint64_t GetFirstFullTokenID(); + + static uint64_t GetSelfTokenID(); + static std::string GetLocalDeviceID(); static std::string GetCallingDeviceID(); diff --git a/mock/innerkits/ipc/ipc_core/include/ipc_types.h b/mock/innerkits/ipc/ipc_core/include/ipc_types.h index 66b46ad1..97c40300 100644 --- a/mock/innerkits/ipc/ipc_core/include/ipc_types.h +++ b/mock/innerkits/ipc/ipc_core/include/ipc_types.h @@ -35,15 +35,15 @@ enum { SYSPROPS_TRANSACTION = ZIPC_PACK_CHARS('_', 'S', 'P', 'R'), SYNCHRONIZE_REFERENCE = ZIPC_PACK_CHARS('_', 'S', 'Y', 'C'), INVOKE_LISTEN_THREAD = ZIPC_PACK_CHARS('_', 'I', 'L', 'T'), + GET_PID_UID = ZIPC_PACK_CHARS('_', 'G', 'P', 'U'), GET_PROTO_INFO = ZIPC_PACK_CHARS('_', 'G', 'R', 'I'), - GET_UIDPID_INFO = ZIPC_PACK_CHARS('_', 'G', 'U', 'I'), - GRANT_DATABUS_NAME = ZIPC_PACK_CHARS('_', 'G', 'D', 'N'), - TRANS_DATABUS_NAME = ZIPC_PACK_CHARS('_', 'T', 'D', 'N'), + GET_SESSION_NAME = ZIPC_PACK_CHARS('_', 'G', 'S', 'N'), + GET_SESSION_NAME_PID_UID = ZIPC_PACK_CHARS('_', 'G', 'S', 'P'), + GET_GRANTED_SESSION_NAME = ZIPC_PACK_CHARS('_', 'G', 'G', 'S'), DBINDER_OBITUARY_TRANSACTION = ZIPC_PACK_CHARS('_', 'D', 'O', 'T'), DBINDER_INCREFS_TRANSACTION = ZIPC_PACK_CHARS('_', 'D', 'I', 'T'), DBINDER_DECREFS_TRANSACTION = ZIPC_PACK_CHARS('_', 'D', 'D', 'T'), DBINDER_ADD_COMMAUTH = ZIPC_PACK_CHARS('_', 'D', 'A', 'C'), - DBINDER_TRANS_COMMAUTH = ZIPC_PACK_CHARS('_', 'D', 'T', 'C'), TRANS_SYNC = 0, TRANS_ASYNC = 1, }; diff --git a/mock/innerkits/ipc/ipc_core/include/iremote_broker.h b/mock/innerkits/ipc/ipc_core/include/iremote_broker.h index 7105ff77..c09c4d47 100644 --- a/mock/innerkits/ipc/ipc_core/include/iremote_broker.h +++ b/mock/innerkits/ipc/ipc_core/include/iremote_broker.h @@ -40,18 +40,23 @@ public: class IRemoteBroker : public virtual RefBase { public: IRemoteBroker() = default; - virtual ~IRemoteBroker() = default; + virtual ~IRemoteBroker() override = default; virtual sptr AsObject() = 0; - static inline sptr AsImplement(const sptr &object) - { - (void)object; - return nullptr; - } +}; + +class BrokerDelegatorBase { +public: + BrokerDelegatorBase() = default; + virtual ~BrokerDelegatorBase() = default; + +public: + bool isSoUnloaded = false; + std::u16string descriptor_; }; #define DECLARE_INTERFACE_DESCRIPTOR(DESCRIPTOR) \ - static inline const std::u16string metaDescriptor_ = { DESCRIPTOR }; \ - static inline const std::u16string &GetDescriptor() \ + static constexpr const char16_t *metaDescriptor_ = DESCRIPTOR; \ + static inline const std::u16string GetDescriptor() \ { \ return metaDescriptor_; \ } @@ -61,7 +66,7 @@ class BrokerRegistration { public: static BrokerRegistration &Get(); - bool Register(const std::u16string &descriptor, const Constructor &creator); + bool Register(const std::u16string &descriptor, const Constructor &creator, const BrokerDelegatorBase *object); void Unregister(const std::u16string &descriptor); sptr NewInstance(const std::u16string &descriptor, const sptr &object); @@ -76,12 +81,14 @@ private: BrokerRegistration &operator = (BrokerRegistration &&) = delete; std::mutex creatorMutex_; std::unordered_map creators_; + std::vector objects_; + std::atomic isUnloading = false; }; -template class BrokerDelegator { +template class BrokerDelegator : public BrokerDelegatorBase { public: BrokerDelegator(); - ~BrokerDelegator(); + ~BrokerDelegator() override; private: BrokerDelegator(const BrokerDelegator &) = delete; @@ -94,14 +101,17 @@ template BrokerDelegator::BrokerDelegator() { const std::u16string descriptor = T::GetDescriptor(); BrokerRegistration ®istration = BrokerRegistration::Get(); - registration.Register(descriptor, BrokerCreator()); + if (registration.Register(descriptor, BrokerCreator(), this)) { + descriptor_ = T::GetDescriptor(); + } } template BrokerDelegator::~BrokerDelegator() { - const std::u16string descriptor = T::GetDescriptor(); - BrokerRegistration ®istration = BrokerRegistration::Get(); - registration.Unregister(descriptor); + if (!isSoUnloaded && !descriptor_.empty()) { + BrokerRegistration ®istration = BrokerRegistration::Get(); + registration.Unregister(descriptor_); + } } template inline sptr iface_cast(const sptr &object) diff --git a/mock/innerkits/ipc/ipc_core/include/iremote_object.h b/mock/innerkits/ipc/ipc_core/include/iremote_object.h index 67ef09e1..6e4161b5 100644 --- a/mock/innerkits/ipc/ipc_core/include/iremote_object.h +++ b/mock/innerkits/ipc/ipc_core/include/iremote_object.h @@ -66,7 +66,7 @@ public: virtual bool RemoveDeathRecipient(const sptr &recipient) = 0; - bool Marshalling(Parcel &parcel) const override; + virtual bool Marshalling(Parcel &parcel) const override; static sptr Unmarshalling(Parcel &parcel); diff --git a/mock/innerkits/ipc/libdbinder/include/dbinder_service.h b/mock/innerkits/ipc/libdbinder/include/dbinder_service.h index 4bea9ad3..54758c52 100644 --- a/mock/innerkits/ipc/libdbinder/include/dbinder_service.h +++ b/mock/innerkits/ipc/libdbinder/include/dbinder_service.h @@ -54,7 +54,8 @@ struct DHandleEntryTxRx { struct DHandleEntryHead head; uint32_t transType; uint32_t dBinderCode; - uint32_t rpcFeatureSet; + uint16_t fromPort; + uint16_t toPort; uint64_t stubIndex; uint32_t seqNumber; binder_uintptr_t binderObject; @@ -69,7 +70,8 @@ struct DHandleEntryTxRx { struct SessionInfo { uint32_t seqNumber; uint32_t type; - uint32_t rpcFeatureSet; + uint16_t toPort; + uint16_t fromPort; uint64_t stubIndex; uint32_t socketFd; std::string serviceName; @@ -80,16 +82,29 @@ enum DBinderCode { MESSAGE_AS_INVOKER = 1, MESSAGE_AS_REPLY = 2, MESSAGE_AS_OBITUARY = 3, + MESSAGE_AS_REMOTE_ERROR = 4, + MESSAGE_AS_REPLY_TOKENID = 5, }; -enum AfType { - IPV4_TYPE = 1, - IPV6_TYPE = 2, - DATABBUS_TYPE = 3, +enum DBinderErrorCode { + DBINDER_OK = 100, + STUB_INVALID = 101, + SEND_MESSAGE_FAILED = 102, + MAKE_THREADLOCK_FAILED = 103, + WAIT_REPLY_TIMEOUT = 104, + QUERY_REPLY_SESSION_FAILED = 105, + SA_NOT_FOUND = 106, + SA_INVOKE_FAILED = 107, + DEVICEID_INVALID = 108, + SESSION_NAME_NOT_FOUND = 109, + WRITE_PARCEL_FAILED = 110, + INVOKE_STUB_THREAD_FAILED = 111, + SESSION_NAME_INVALID = 112, }; struct ThreadLockInfo { std::mutex mutex; + std::string networkId; std::condition_variable condition; bool ready = false; }; @@ -100,12 +115,14 @@ public: virtual ~DBinderService(); public: static sptr GetInstance(); + static std::string ConvertToSecureDeviceID(const std::string &deviceID); bool StartDBinderService(std::shared_ptr &callbackImpl); sptr MakeRemoteBinder(const std::u16string &serviceName, - const std::string &deviceID, binder_uintptr_t binderObject, uint64_t pid = 0); + const std::string &deviceID, int32_t binderObject, uint32_t pid = 0, uint32_t uid = 0); bool RegisterRemoteProxy(std::u16string serviceName, sptr binderObject); bool RegisterRemoteProxy(std::u16string serviceName, int32_t systemAbilityId); - bool OnRemoteMessageTask(const struct DHandleEntryTxRx *message); + bool OnRemoteMessageTask(std::shared_ptr message); + void AddAsynMessageTask(std::shared_ptr message); std::shared_ptr QuerySessionObject(binder_uintptr_t stub); bool DetachDeathRecipient(sptr object); bool AttachDeathRecipient(sptr object, sptr deathRecipient); @@ -114,32 +131,33 @@ public: bool AttachCallbackProxy(sptr object, DBinderServiceStub *dbStub); int32_t NoticeServiceDie(const std::u16string &serviceName, const std::string &deviceID); int32_t NoticeDeviceDie(const std::string &deviceID); - bool AttachBusNameObject(IPCObjectProxy *proxy, const std::string &name); - bool DetachBusNameObject(IPCObjectProxy *proxy); std::string CreateDatabusName(int uid, int pid); bool DetachProxyObject(binder_uintptr_t binderObject); - std::string QueryBusNameObject(IPCObjectProxy *proxy); + void LoadSystemAbilityComplete(const std::string& srcNetworkId, int32_t systemAbilityId, + const sptr& remoteObject); + bool ProcessOnSessionClosed(std::shared_ptr session); private: static std::shared_ptr GetRemoteListener(); static bool StartRemoteListener(); static void StopRemoteListener(); - static std::string ConvertToSecureDeviceID(const std::string &deviceID); std::u16string GetRegisterService(binder_uintptr_t binderObject); - bool InvokerRemoteDBinder(const sptr stub, uint32_t seqNumber); + int32_t InvokerRemoteDBinder(const sptr stub, uint32_t seqNumber, uint32_t pid, uint32_t uid); bool OnRemoteReplyMessage(const struct DHandleEntryTxRx *replyMessage); + bool OnRemoteErrorMessage(const struct DHandleEntryTxRx *replyMessage); void MakeSessionByReplyMessage(const struct DHandleEntryTxRx *replyMessage); bool OnRemoteInvokerMessage(const struct DHandleEntryTxRx *message); void WakeupThreadByStub(uint32_t seqNumber); void DetachThreadLockInfo(uint32_t seqNumber); - bool AttachThreadLockInfo(uint32_t seqNumber, std::shared_ptr object); + bool AttachThreadLockInfo(uint32_t seqNumber, const std::string &networkId, + std::shared_ptr object); std::shared_ptr QueryThreadLockInfo(uint32_t seqNumber); bool AttachProxyObject(sptr object, binder_uintptr_t binderObject); sptr QueryProxyObject(binder_uintptr_t binderObject); bool DetachSessionObject(binder_uintptr_t stub); bool AttachSessionObject(std::shared_ptr object, binder_uintptr_t stub); sptr FindOrNewProxy(binder_uintptr_t binderObject, int32_t systemAbilityId); - bool SendEntryToRemote(const sptr stub, uint32_t seqNumber); + bool SendEntryToRemote(const sptr stub, uint32_t seqNumber, uint32_t pid, uint32_t uid); uint16_t AllocFreeSocketPort(); std::string GetLocalDeviceID(); bool CheckBinderObject(const sptr &stub, binder_uintptr_t binderObject); @@ -155,38 +173,46 @@ private: std::list FindServicesByDeviceID(const std::string &deviceID); int32_t NoticeServiceDieInner(const std::u16string &serviceName, const std::string &deviceID); uint32_t GetRemoteTransType(); - bool OnRemoteInvokerDataBusMessage(IPCObjectProxy *proxy, struct DHandleEntryTxRx *replyMessage, - std::string &remoteDeviceId, int pid, int uid); + uint32_t OnRemoteInvokerDataBusMessage(IPCObjectProxy *proxy, struct DHandleEntryTxRx *replyMessage, + std::string &remoteDeviceId, int pid, int uid, uint32_t tokenId); bool IsDeviceIdIllegal(const std::string &deviceID); std::string GetDatabusNameByProxy(IPCObjectProxy *proxy); uint32_t GetSeqNumber(); + bool StartThreadPool(); + bool StopThreadPool(); + bool AddAsynTask(const ThreadPool::Task &f); + bool IsSameSession(std::shared_ptr oldSession, std::shared_ptr newSession); bool RegisterRemoteProxyInner(std::u16string serviceName, binder_uintptr_t binder); bool CheckSystemAbilityId(int32_t systemAbilityId); - bool IsSameSession(std::shared_ptr oldSession, std::shared_ptr nowSession); bool HandleInvokeListenThread(IPCObjectProxy *proxy, uint64_t stubIndex, std::string serverSessionName, struct DHandleEntryTxRx *replyMessage); bool ReStartRemoteListener(); - bool ReGrantPermission(const std::string &sessionName); + bool IsSameLoadSaItem(const std::string& srcNetworkId, int32_t systemAbilityId, + std::shared_ptr loadSaItem); + std::shared_ptr PopLoadSaItem(const std::string& srcNetworkId, int32_t systemAbilityId); + void SendMessageToRemote(uint32_t dBinderCode, uint32_t reason, + std::shared_ptr replyMessage); private: DISALLOW_COPY_AND_MOVE(DBinderService); static std::mutex instanceMutex_; - static constexpr int WAIT_FOR_REPLY_MAX_SEC = 4; + static constexpr int WAIT_FOR_REPLY_MAX_SEC = 8; static constexpr int RETRY_TIMES = 2; static std::shared_ptr remoteListener_; static bool mainThreadCreated_; static sptr instance_; std::shared_mutex remoteBinderMutex_; - std::shared_mutex busNameMutex_; std::shared_mutex proxyMutex_; std::shared_mutex deathRecipientMutex_; std::shared_mutex sessionMutex_; + std::shared_mutex loadSaMutex_; std::mutex handleEntryMutex_; std::mutex threadLockMutex_; std::mutex callbackProxyMutex_; std::mutex deathNotificationMutex_; + std::mutex threadPoolMutex_; uint32_t seqNumber_ = 0; /* indicate make remote binder message sequence number, and can be overflow */ std::list> DBinderStubRegisted_; @@ -196,7 +222,9 @@ private: std::map> sessionObject_; std::map, DBinderServiceStub *> noticeProxy_; std::map, sptr> deathRecipients_; - std::map busNameObject_; + bool threadPoolStarted_ = false; + int32_t threadPoolNumber_ = 4; + std::unique_ptr threadPool_ = nullptr; static constexpr int32_t FIRST_SYS_ABILITY_ID = 0x00000001; static constexpr int32_t LAST_SYS_ABILITY_ID = 0x00ffffff; diff --git a/mock/innerkits/ipc/libdbinder/include/dbinder_service_stub.h b/mock/innerkits/ipc/libdbinder/include/dbinder_service_stub.h index 93c8f126..e502acd4 100644 --- a/mock/innerkits/ipc/libdbinder/include/dbinder_service_stub.h +++ b/mock/innerkits/ipc/libdbinder/include/dbinder_service_stub.h @@ -21,18 +21,22 @@ #include "ipc_object_stub.h" namespace OHOS { +#ifdef BINDER_IPC_32BIT +typedef unsigned int binder_uintptr_t; +#else typedef unsigned long long binder_uintptr_t; +#endif class DBinderServiceStub : public IPCObjectStub { public: - explicit DBinderServiceStub(const std::string& serviceName, const std::string& deviceID, + explicit DBinderServiceStub(const std::string &serviceName, const std::string &deviceID, binder_uintptr_t binderObject); ~DBinderServiceStub(); int32_t ProcessProto(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) override; int32_t OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) override; - const std::string& GetServiceName(); - const std::string& GetDeviceID(); + const std::string &GetServiceName(); + const std::string &GetDeviceID(); binder_uintptr_t GetBinderObject() const; private: diff --git a/mock/sqlite/include/sqlite3.h b/mock/sqlite/include/sqlite3.h index 9f89fdcc..020b3ad8 100644 --- a/mock/sqlite/include/sqlite3.h +++ b/mock/sqlite/include/sqlite3.h @@ -288,18 +288,18 @@ typedef struct sqlite3 sqlite3; ** between 0 and +18446744073709551615 inclusive. */ #ifdef SQLITE_INT64_TYPE -typedef SQLITE_INT64_TYPE sqlite_int64; + typedef SQLITE_INT64_TYPE sqlite_int64; # ifdef SQLITE_UINT64_TYPE -typedef SQLITE_UINT64_TYPE sqlite_uint64; + typedef SQLITE_UINT64_TYPE sqlite_uint64; # else -typedef unsigned SQLITE_INT64_TYPE sqlite_uint64; + typedef unsigned SQLITE_INT64_TYPE sqlite_uint64; # endif #elif defined(_MSC_VER) || defined(__BORLANDC__) -typedef __int64 sqlite_int64; -typedef unsigned __int64 sqlite_uint64; + typedef __int64 sqlite_int64; + typedef unsigned __int64 sqlite_uint64; #else -typedef long long int sqlite_int64; -typedef unsigned long long int sqlite_uint64; + typedef long long int sqlite_int64; + typedef unsigned long long int sqlite_uint64; #endif typedef sqlite_int64 sqlite3_int64; typedef sqlite_uint64 sqlite3_uint64; @@ -423,11 +423,11 @@ typedef int (*sqlite3_callback)(void*,int,char**, char**); ** */ SQLITE_API int sqlite3_exec( - sqlite3*, /* An open database */ - const char *sql, /* SQL to be evaluated */ - int (*callback)(void*,int,char**,char**), /* Callback function */ - void *, /* 1st argument to callback */ - char **errmsg /* Error msg written here */ + sqlite3*, /* An open database */ + const char *sql, /* SQL to be evaluated */ + int (*callback)(void*,int,char**,char**), /* Callback function */ + void *, /* 1st argument to callback */ + char **errmsg /* Error msg written here */ ); /* @@ -721,7 +721,7 @@ SQLITE_API int sqlite3_exec( */ typedef struct sqlite3_file sqlite3_file; struct sqlite3_file { - const struct sqlite3_io_methods *pMethods; /* Methods for an open file */ + const struct sqlite3_io_methods *pMethods; /* Methods for an open file */ }; /* @@ -820,29 +820,29 @@ struct sqlite3_file { */ typedef struct sqlite3_io_methods sqlite3_io_methods; struct sqlite3_io_methods { - int iVersion; - int (*xClose)(sqlite3_file*); - int (*xRead)(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst); - int (*xWrite)(sqlite3_file*, const void*, int iAmt, sqlite3_int64 iOfst); - int (*xTruncate)(sqlite3_file*, sqlite3_int64 size); - int (*xSync)(sqlite3_file*, int flags); - int (*xFileSize)(sqlite3_file*, sqlite3_int64 *pSize); - int (*xLock)(sqlite3_file*, int); - int (*xUnlock)(sqlite3_file*, int); - int (*xCheckReservedLock)(sqlite3_file*, int *pResOut); - int (*xFileControl)(sqlite3_file*, int op, void *pArg); - int (*xSectorSize)(sqlite3_file*); - int (*xDeviceCharacteristics)(sqlite3_file*); - /* Methods above are valid for version 1 */ - int (*xShmMap)(sqlite3_file*, int iPg, int pgsz, int, void volatile**); - int (*xShmLock)(sqlite3_file*, int offset, int n, int flags); - void (*xShmBarrier)(sqlite3_file*); - int (*xShmUnmap)(sqlite3_file*, int deleteFlag); - /* Methods above are valid for version 2 */ - int (*xFetch)(sqlite3_file*, sqlite3_int64 iOfst, int iAmt, void **pp); - int (*xUnfetch)(sqlite3_file*, sqlite3_int64 iOfst, void *p); - /* Methods above are valid for version 3 */ - /* Additional methods may be added in future releases */ + int iVersion; + int (*xClose)(sqlite3_file*); + int (*xRead)(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst); + int (*xWrite)(sqlite3_file*, const void*, int iAmt, sqlite3_int64 iOfst); + int (*xTruncate)(sqlite3_file*, sqlite3_int64 size); + int (*xSync)(sqlite3_file*, int flags); + int (*xFileSize)(sqlite3_file*, sqlite3_int64 *pSize); + int (*xLock)(sqlite3_file*, int); + int (*xUnlock)(sqlite3_file*, int); + int (*xCheckReservedLock)(sqlite3_file*, int *pResOut); + int (*xFileControl)(sqlite3_file*, int op, void *pArg); + int (*xSectorSize)(sqlite3_file*); + int (*xDeviceCharacteristics)(sqlite3_file*); + /* Methods above are valid for version 1 */ + int (*xShmMap)(sqlite3_file*, int iPg, int pgsz, int, void volatile**); + int (*xShmLock)(sqlite3_file*, int offset, int n, int flags); + void (*xShmBarrier)(sqlite3_file*); + int (*xShmUnmap)(sqlite3_file*, int deleteFlag); + /* Methods above are valid for version 2 */ + int (*xFetch)(sqlite3_file*, sqlite3_int64 iOfst, int iAmt, void **pp); + int (*xUnfetch)(sqlite3_file*, sqlite3_int64 iOfst, void *p); + /* Methods above are valid for version 3 */ + /* Additional methods may be added in future releases */ }; /* @@ -1425,38 +1425,38 @@ typedef struct sqlite3_api_routines sqlite3_api_routines; typedef struct sqlite3_vfs sqlite3_vfs; typedef void (*sqlite3_syscall_ptr)(void); struct sqlite3_vfs { - int iVersion; /* Structure version number (currently 3) */ - int szOsFile; /* Size of subclassed sqlite3_file */ - int mxPathname; /* Maximum file pathname length */ - sqlite3_vfs *pNext; /* Next registered VFS */ - const char *zName; /* Name of this virtual file system */ - void *pAppData; /* Pointer to application-specific data */ - int (*xOpen)(sqlite3_vfs*, const char *zName, sqlite3_file*, - int flags, int *pOutFlags); - int (*xDelete)(sqlite3_vfs*, const char *zName, int syncDir); - int (*xAccess)(sqlite3_vfs*, const char *zName, int flags, int *pResOut); - int (*xFullPathname)(sqlite3_vfs*, const char *zName, int nOut, char *zOut); - void *(*xDlOpen)(sqlite3_vfs*, const char *zFilename); - void (*xDlError)(sqlite3_vfs*, int nByte, char *zErrMsg); - void (*(*xDlSym)(sqlite3_vfs*,void*, const char *zSymbol))(void); - void (*xDlClose)(sqlite3_vfs*, void*); - int (*xRandomness)(sqlite3_vfs*, int nByte, char *zOut); - int (*xSleep)(sqlite3_vfs*, int microseconds); - int (*xCurrentTime)(sqlite3_vfs*, double*); - int (*xGetLastError)(sqlite3_vfs*, int, char *); - /* + int iVersion; /* Structure version number (currently 3) */ + int szOsFile; /* Size of subclassed sqlite3_file */ + int mxPathname; /* Maximum file pathname length */ + sqlite3_vfs *pNext; /* Next registered VFS */ + const char *zName; /* Name of this virtual file system */ + void *pAppData; /* Pointer to application-specific data */ + int (*xOpen)(sqlite3_vfs*, const char *zName, sqlite3_file*, + int flags, int *pOutFlags); + int (*xDelete)(sqlite3_vfs*, const char *zName, int syncDir); + int (*xAccess)(sqlite3_vfs*, const char *zName, int flags, int *pResOut); + int (*xFullPathname)(sqlite3_vfs*, const char *zName, int nOut, char *zOut); + void *(*xDlOpen)(sqlite3_vfs*, const char *zFilename); + void (*xDlError)(sqlite3_vfs*, int nByte, char *zErrMsg); + void (*(*xDlSym)(sqlite3_vfs*,void*, const char *zSymbol))(void); + void (*xDlClose)(sqlite3_vfs*, void*); + int (*xRandomness)(sqlite3_vfs*, int nByte, char *zOut); + int (*xSleep)(sqlite3_vfs*, int microseconds); + int (*xCurrentTime)(sqlite3_vfs*, double*); + int (*xGetLastError)(sqlite3_vfs*, int, char *); + /* ** The methods above are in version 1 of the sqlite_vfs object ** definition. Those that follow are added in version 2 or later */ - int (*xCurrentTimeInt64)(sqlite3_vfs*, sqlite3_int64*); - /* + int (*xCurrentTimeInt64)(sqlite3_vfs*, sqlite3_int64*); + /* ** The methods above are in versions 1 and 2 of the sqlite_vfs object. ** Those below are for version 3 and greater. */ - int (*xSetSystemCall)(sqlite3_vfs*, const char *zName, sqlite3_syscall_ptr); - sqlite3_syscall_ptr (*xGetSystemCall)(sqlite3_vfs*, const char *zName); - const char *(*xNextSystemCall)(sqlite3_vfs*, const char *zName); - /* + int (*xSetSystemCall)(sqlite3_vfs*, const char *zName, sqlite3_syscall_ptr); + sqlite3_syscall_ptr (*xGetSystemCall)(sqlite3_vfs*, const char *zName); + const char *(*xNextSystemCall)(sqlite3_vfs*, const char *zName); + /* ** The methods above are in versions 1 through 3 of the sqlite_vfs object. ** New fields may be appended in future versions. The iVersion ** value will increment whenever this happens. @@ -1722,14 +1722,14 @@ SQLITE_API int sqlite3_db_config(sqlite3*, int op, ...); */ typedef struct sqlite3_mem_methods sqlite3_mem_methods; struct sqlite3_mem_methods { - void *(*xMalloc)(int); /* Memory allocation function */ - void (*xFree)(void*); /* Free a prior allocation */ - void *(*xRealloc)(void*,int); /* Resize an allocation */ - int (*xSize)(void*); /* Return the size of an allocation */ - int (*xRoundup)(int); /* Round up request size to allocation size */ - int (*xInit)(void*); /* Initialize the memory allocator */ - void (*xShutdown)(void*); /* Deinitialize the memory allocator */ - void *pAppData; /* Argument to xInit() and xShutdown() */ + void *(*xMalloc)(int); /* Memory allocation function */ + void (*xFree)(void*); /* Free a prior allocation */ + void *(*xRealloc)(void*,int); /* Resize an allocation */ + int (*xSize)(void*); /* Return the size of an allocation */ + int (*xRoundup)(int); /* Round up request size to allocation size */ + int (*xInit)(void*); /* Initialize the memory allocator */ + void (*xShutdown)(void*); /* Deinitialize the memory allocator */ + void *pAppData; /* Argument to xInit() and xShutdown() */ }; /* @@ -2833,12 +2833,12 @@ SQLITE_API int sqlite3_busy_timeout(sqlite3*, int ms); ** [sqlite3_errmsg()]. */ SQLITE_API int sqlite3_get_table( - sqlite3 *db, /* An open database */ - const char *zSql, /* SQL to be evaluated */ - char ***pazResult, /* Results of the query */ - int *pnRow, /* Number of result rows written here */ - int *pnColumn, /* Number of result columns written here */ - char **pzErrmsg /* Error msg written here */ + sqlite3 *db, /* An open database */ + const char *zSql, /* SQL to be evaluated */ + char ***pazResult, /* Results of the query */ + int *pnRow, /* Number of result rows written here */ + int *pnColumn, /* Number of result columns written here */ + char **pzErrmsg /* Error msg written here */ ); SQLITE_API void sqlite3_free_table(char **result); @@ -3108,15 +3108,15 @@ SQLITE_API void sqlite3_randomness(int N, void *P); ** sqlite3_prepare_v2() to reprepare a statement after a schema change. */ SQLITE_API int sqlite3_set_authorizer( - sqlite3*, - int (*xAuth)(void*,int,const char*,const char*,const char*,const char*), - void *pUserData + sqlite3*, + int (*xAuth)(void*,int,const char*,const char*,const char*,const char*), + void *pUserData ); #ifdef SQLITE_ENABLE_DROPTABLE_CALLBACK SQLITE_API int sqlite3_set_droptable_handle( - sqlite3 *db, - void (*xFunc)(sqlite3*,const char*,const char*) + sqlite3 *db, + void (*xFunc)(sqlite3*,const char*,const char*) ); #endif @@ -3223,9 +3223,9 @@ SQLITE_API int sqlite3_set_droptable_handle( ** profile callback. */ SQLITE_API SQLITE_DEPRECATED void *sqlite3_trace(sqlite3*, - void(*xTrace)(void*,const char*), void*); + void(*xTrace)(void*,const char*), void*); SQLITE_API SQLITE_DEPRECATED void *sqlite3_profile(sqlite3*, - void(*xProfile)(void*,const char*,sqlite3_uint64), void*); + void(*xProfile)(void*,const char*,sqlite3_uint64), void*); /* ** CAPI3REF: SQL Trace Event Codes @@ -3314,10 +3314,10 @@ SQLITE_API SQLITE_DEPRECATED void *sqlite3_profile(sqlite3*, ** are deprecated. */ SQLITE_API int sqlite3_trace_v2( - sqlite3*, - unsigned uMask, - int(*xCallback)(unsigned,void*,void*,void*), - void *pCtx + sqlite3*, + unsigned uMask, + int(*xCallback)(unsigned,void*,void*,void*), + void *pCtx ); /* @@ -3625,18 +3625,18 @@ SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*); ** See also: [sqlite3_temp_directory] */ SQLITE_API int sqlite3_open( - const char *filename, /* Database filename (UTF-8) */ - sqlite3 **ppDb /* OUT: SQLite db handle */ + const char *filename, /* Database filename (UTF-8) */ + sqlite3 **ppDb /* OUT: SQLite db handle */ ); SQLITE_API int sqlite3_open16( - const void *filename, /* Database filename (UTF-16) */ - sqlite3 **ppDb /* OUT: SQLite db handle */ + const void *filename, /* Database filename (UTF-16) */ + sqlite3 **ppDb /* OUT: SQLite db handle */ ); SQLITE_API int sqlite3_open_v2( - const char *filename, /* Database filename (UTF-8) */ - sqlite3 **ppDb, /* OUT: SQLite db handle */ - int flags, /* Flags */ - const char *zVfs /* Name of VFS module to use */ + const char *filename, /* Database filename (UTF-8) */ + sqlite3 **ppDb, /* OUT: SQLite db handle */ + int flags, /* Flags */ + const char *zVfs /* Name of VFS module to use */ ); /* @@ -3806,11 +3806,11 @@ SQLITE_API sqlite3_file *sqlite3_database_file_object(const char*); ** invoked prior to calling sqlite3_free_filename(Y). */ SQLITE_API char *sqlite3_create_filename( - const char *zDatabase, - const char *zJournal, - const char *zWal, - int nParam, - const char **azParam + const char *zDatabase, + const char *zJournal, + const char *zWal, + int nParam, + const char **azParam ); SQLITE_API void sqlite3_free_filename(char*); @@ -4149,48 +4149,48 @@ SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal); ** sqlite3_prepare_v3() with a zero prepFlags parameter. */ SQLITE_API int sqlite3_prepare( - sqlite3 *db, /* Database handle */ - const char *zSql, /* SQL statement, UTF-8 encoded */ - int nByte, /* Maximum length of zSql in bytes. */ - sqlite3_stmt **ppStmt, /* OUT: Statement handle */ - const char **pzTail /* OUT: Pointer to unused portion of zSql */ + sqlite3 *db, /* Database handle */ + const char *zSql, /* SQL statement, UTF-8 encoded */ + int nByte, /* Maximum length of zSql in bytes. */ + sqlite3_stmt **ppStmt, /* OUT: Statement handle */ + const char **pzTail /* OUT: Pointer to unused portion of zSql */ ); SQLITE_API int sqlite3_prepare_v2( - sqlite3 *db, /* Database handle */ - const char *zSql, /* SQL statement, UTF-8 encoded */ - int nByte, /* Maximum length of zSql in bytes. */ - sqlite3_stmt **ppStmt, /* OUT: Statement handle */ - const char **pzTail /* OUT: Pointer to unused portion of zSql */ + sqlite3 *db, /* Database handle */ + const char *zSql, /* SQL statement, UTF-8 encoded */ + int nByte, /* Maximum length of zSql in bytes. */ + sqlite3_stmt **ppStmt, /* OUT: Statement handle */ + const char **pzTail /* OUT: Pointer to unused portion of zSql */ ); SQLITE_API int sqlite3_prepare_v3( - sqlite3 *db, /* Database handle */ - const char *zSql, /* SQL statement, UTF-8 encoded */ - int nByte, /* Maximum length of zSql in bytes. */ - unsigned int prepFlags, /* Zero or more SQLITE_PREPARE_ flags */ - sqlite3_stmt **ppStmt, /* OUT: Statement handle */ - const char **pzTail /* OUT: Pointer to unused portion of zSql */ + sqlite3 *db, /* Database handle */ + const char *zSql, /* SQL statement, UTF-8 encoded */ + int nByte, /* Maximum length of zSql in bytes. */ + unsigned int prepFlags, /* Zero or more SQLITE_PREPARE_ flags */ + sqlite3_stmt **ppStmt, /* OUT: Statement handle */ + const char **pzTail /* OUT: Pointer to unused portion of zSql */ ); SQLITE_API int sqlite3_prepare16( - sqlite3 *db, /* Database handle */ - const void *zSql, /* SQL statement, UTF-16 encoded */ - int nByte, /* Maximum length of zSql in bytes. */ - sqlite3_stmt **ppStmt, /* OUT: Statement handle */ - const void **pzTail /* OUT: Pointer to unused portion of zSql */ + sqlite3 *db, /* Database handle */ + const void *zSql, /* SQL statement, UTF-16 encoded */ + int nByte, /* Maximum length of zSql in bytes. */ + sqlite3_stmt **ppStmt, /* OUT: Statement handle */ + const void **pzTail /* OUT: Pointer to unused portion of zSql */ ); SQLITE_API int sqlite3_prepare16_v2( - sqlite3 *db, /* Database handle */ - const void *zSql, /* SQL statement, UTF-16 encoded */ - int nByte, /* Maximum length of zSql in bytes. */ - sqlite3_stmt **ppStmt, /* OUT: Statement handle */ - const void **pzTail /* OUT: Pointer to unused portion of zSql */ + sqlite3 *db, /* Database handle */ + const void *zSql, /* SQL statement, UTF-16 encoded */ + int nByte, /* Maximum length of zSql in bytes. */ + sqlite3_stmt **ppStmt, /* OUT: Statement handle */ + const void **pzTail /* OUT: Pointer to unused portion of zSql */ ); SQLITE_API int sqlite3_prepare16_v3( - sqlite3 *db, /* Database handle */ - const void *zSql, /* SQL statement, UTF-16 encoded */ - int nByte, /* Maximum length of zSql in bytes. */ - unsigned int prepFlags, /* Zero or more SQLITE_PREPARE_ flags */ - sqlite3_stmt **ppStmt, /* OUT: Statement handle */ - const void **pzTail /* OUT: Pointer to unused portion of zSql */ + sqlite3 *db, /* Database handle */ + const void *zSql, /* SQL statement, UTF-16 encoded */ + int nByte, /* Maximum length of zSql in bytes. */ + unsigned int prepFlags, /* Zero or more SQLITE_PREPARE_ flags */ + sqlite3_stmt **ppStmt, /* OUT: Statement handle */ + const void **pzTail /* OUT: Pointer to unused portion of zSql */ ); /* @@ -4516,7 +4516,7 @@ typedef struct sqlite3_context sqlite3_context; */ SQLITE_API int sqlite3_bind_blob(sqlite3_stmt*, int, const void*, int n, void(*)(void*)); SQLITE_API int sqlite3_bind_blob64(sqlite3_stmt*, int, const void*, sqlite3_uint64, - void(*)(void*)); + void(*)(void*)); SQLITE_API int sqlite3_bind_double(sqlite3_stmt*, int, double); SQLITE_API int sqlite3_bind_int(sqlite3_stmt*, int, int); SQLITE_API int sqlite3_bind_int64(sqlite3_stmt*, int, sqlite3_int64); @@ -4524,7 +4524,7 @@ SQLITE_API int sqlite3_bind_null(sqlite3_stmt*, int); SQLITE_API int sqlite3_bind_text(sqlite3_stmt*,int,const char*,int,void(*)(void*)); SQLITE_API int sqlite3_bind_text16(sqlite3_stmt*, int, const void*, int, void(*)(void*)); SQLITE_API int sqlite3_bind_text64(sqlite3_stmt*, int, const char*, sqlite3_uint64, - void(*)(void*), unsigned char encoding); + void(*)(void*), unsigned char encoding); SQLITE_API int sqlite3_bind_value(sqlite3_stmt*, int, const sqlite3_value*); SQLITE_API int sqlite3_bind_pointer(sqlite3_stmt*, int, void*, const char*,void(*)(void*)); SQLITE_API int sqlite3_bind_zeroblob(sqlite3_stmt*, int, int n); @@ -5271,47 +5271,47 @@ SQLITE_API int sqlite3_reset(sqlite3_stmt *pStmt); ** statement in which the function is running. */ SQLITE_API int sqlite3_create_function( - sqlite3 *db, - const char *zFunctionName, - int nArg, - int eTextRep, - void *pApp, - void (*xFunc)(sqlite3_context*,int,sqlite3_value**), - void (*xStep)(sqlite3_context*,int,sqlite3_value**), - void (*xFinal)(sqlite3_context*) + sqlite3 *db, + const char *zFunctionName, + int nArg, + int eTextRep, + void *pApp, + void (*xFunc)(sqlite3_context*,int,sqlite3_value**), + void (*xStep)(sqlite3_context*,int,sqlite3_value**), + void (*xFinal)(sqlite3_context*) ); SQLITE_API int sqlite3_create_function16( - sqlite3 *db, - const void *zFunctionName, - int nArg, - int eTextRep, - void *pApp, - void (*xFunc)(sqlite3_context*,int,sqlite3_value**), - void (*xStep)(sqlite3_context*,int,sqlite3_value**), - void (*xFinal)(sqlite3_context*) + sqlite3 *db, + const void *zFunctionName, + int nArg, + int eTextRep, + void *pApp, + void (*xFunc)(sqlite3_context*,int,sqlite3_value**), + void (*xStep)(sqlite3_context*,int,sqlite3_value**), + void (*xFinal)(sqlite3_context*) ); SQLITE_API int sqlite3_create_function_v2( - sqlite3 *db, - const char *zFunctionName, - int nArg, - int eTextRep, - void *pApp, - void (*xFunc)(sqlite3_context*,int,sqlite3_value**), - void (*xStep)(sqlite3_context*,int,sqlite3_value**), - void (*xFinal)(sqlite3_context*), - void(*xDestroy)(void*) + sqlite3 *db, + const char *zFunctionName, + int nArg, + int eTextRep, + void *pApp, + void (*xFunc)(sqlite3_context*,int,sqlite3_value**), + void (*xStep)(sqlite3_context*,int,sqlite3_value**), + void (*xFinal)(sqlite3_context*), + void(*xDestroy)(void*) ); SQLITE_API int sqlite3_create_window_function( - sqlite3 *db, - const char *zFunctionName, - int nArg, - int eTextRep, - void *pApp, - void (*xStep)(sqlite3_context*,int,sqlite3_value**), - void (*xFinal)(sqlite3_context*), - void (*xValue)(sqlite3_context*), - void (*xInverse)(sqlite3_context*,int,sqlite3_value**), - void(*xDestroy)(void*) + sqlite3 *db, + const char *zFunctionName, + int nArg, + int eTextRep, + void *pApp, + void (*xStep)(sqlite3_context*,int,sqlite3_value**), + void (*xFinal)(sqlite3_context*), + void (*xValue)(sqlite3_context*), + void (*xInverse)(sqlite3_context*,int,sqlite3_value**), + void(*xDestroy)(void*) ); /* @@ -5414,7 +5414,7 @@ SQLITE_API SQLITE_DEPRECATED int sqlite3_transfer_bindings(sqlite3_stmt*, sqlite SQLITE_API SQLITE_DEPRECATED int sqlite3_global_recover(void); SQLITE_API SQLITE_DEPRECATED void sqlite3_thread_cleanup(void); SQLITE_API SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*)(void*,sqlite3_int64,int), - void*,sqlite3_int64); + void*,sqlite3_int64); #endif /* @@ -5889,7 +5889,7 @@ typedef void (*sqlite3_destructor_type)(void*); */ SQLITE_API void sqlite3_result_blob(sqlite3_context*, const void*, int, void(*)(void*)); SQLITE_API void sqlite3_result_blob64(sqlite3_context*,const void*, - sqlite3_uint64,void(*)(void*)); + sqlite3_uint64,void(*)(void*)); SQLITE_API void sqlite3_result_double(sqlite3_context*, double); SQLITE_API void sqlite3_result_error(sqlite3_context*, const char*, int); SQLITE_API void sqlite3_result_error16(sqlite3_context*, const void*, int); @@ -5901,7 +5901,7 @@ SQLITE_API void sqlite3_result_int64(sqlite3_context*, sqlite3_int64); SQLITE_API void sqlite3_result_null(sqlite3_context*); SQLITE_API void sqlite3_result_text(sqlite3_context*, const char*, int, void(*)(void*)); SQLITE_API void sqlite3_result_text64(sqlite3_context*, const char*,sqlite3_uint64, - void(*)(void*), unsigned char encoding); + void(*)(void*), unsigned char encoding); SQLITE_API void sqlite3_result_text16(sqlite3_context*, const void*, int, void(*)(void*)); SQLITE_API void sqlite3_result_text16le(sqlite3_context*, const void*, int,void(*)(void*)); SQLITE_API void sqlite3_result_text16be(sqlite3_context*, const void*, int,void(*)(void*)); @@ -6007,26 +6007,26 @@ SQLITE_API void sqlite3_result_subtype(sqlite3_context*,unsigned int); ** See also: [sqlite3_collation_needed()] and [sqlite3_collation_needed16()]. */ SQLITE_API int sqlite3_create_collation( - sqlite3*, - const char *zName, - int eTextRep, - void *pArg, - int(*xCompare)(void*,int,const void*,int,const void*) + sqlite3*, + const char *zName, + int eTextRep, + void *pArg, + int(*xCompare)(void*,int,const void*,int,const void*) ); SQLITE_API int sqlite3_create_collation_v2( - sqlite3*, - const char *zName, - int eTextRep, - void *pArg, - int(*xCompare)(void*,int,const void*,int,const void*), - void(*xDestroy)(void*) + sqlite3*, + const char *zName, + int eTextRep, + void *pArg, + int(*xCompare)(void*,int,const void*,int,const void*), + void(*xDestroy)(void*) ); SQLITE_API int sqlite3_create_collation16( - sqlite3*, - const void *zName, - int eTextRep, - void *pArg, - int(*xCompare)(void*,int,const void*,int,const void*) + sqlite3*, + const void *zName, + int eTextRep, + void *pArg, + int(*xCompare)(void*,int,const void*,int,const void*) ); /* @@ -6057,14 +6057,14 @@ SQLITE_API int sqlite3_create_collation16( ** [sqlite3_create_collation_v2()]. */ SQLITE_API int sqlite3_collation_needed( - sqlite3*, - void*, - void(*)(void*,sqlite3*,int eTextRep,const char*) + sqlite3*, + void*, + void(*)(void*,sqlite3*,int eTextRep,const char*) ); SQLITE_API int sqlite3_collation_needed16( - sqlite3*, - void*, - void(*)(void*,sqlite3*,int eTextRep,const void*) + sqlite3*, + void*, + void(*)(void*,sqlite3*,int eTextRep,const void*) ); #ifdef SQLITE_HAS_CODEC @@ -6076,13 +6076,13 @@ SQLITE_API int sqlite3_collation_needed16( ** of SQLite. */ SQLITE_API int sqlite3_key( - sqlite3 *db, /* Database to be rekeyed */ - const void *pKey, int nKey /* The key */ + sqlite3 *db, /* Database to be rekeyed */ + const void *pKey, int nKey /* The key */ ); SQLITE_API int sqlite3_key_v2( - sqlite3 *db, /* Database to be rekeyed */ - const char *zDbName, /* Name of the database */ - const void *pKey, int nKey /* The key */ + sqlite3 *db, /* Database to be rekeyed */ + const char *zDbName, /* Name of the database */ + const void *pKey, int nKey /* The key */ ); /* @@ -6094,13 +6094,13 @@ SQLITE_API int sqlite3_key_v2( ** of SQLite. */ SQLITE_API int sqlite3_rekey( - sqlite3 *db, /* Database to be rekeyed */ - const void *pKey, int nKey /* The new key */ + sqlite3 *db, /* Database to be rekeyed */ + const void *pKey, int nKey /* The new key */ ); SQLITE_API int sqlite3_rekey_v2( - sqlite3 *db, /* Database to be rekeyed */ - const char *zDbName, /* Name of the database */ - const void *pKey, int nKey /* The new key */ + sqlite3 *db, /* Database to be rekeyed */ + const char *zDbName, /* Name of the database */ + const void *pKey, int nKey /* The new key */ ); #endif @@ -6111,7 +6111,7 @@ SQLITE_API int sqlite3_rekey_v2( ** activated, none of the CEROD routines will work. */ SQLITE_API void sqlite3_activate_cerod( - const char *zPassPhrase /* Activation phrase */ + const char *zPassPhrase /* Activation phrase */ ); #endif @@ -6249,8 +6249,8 @@ SQLITE_API SQLITE_EXTERN char *sqlite3_data_directory; ** UTF-8 or UTF-16, respectively. */ SQLITE_API int sqlite3_win32_set_directory( - unsigned long type, /* Identifier for directory being set or reset */ - void *zValue /* New value for directory being set or reset */ + unsigned long type, /* Identifier for directory being set or reset */ + void *zValue /* New value for directory being set or reset */ ); SQLITE_API int sqlite3_win32_set_directory8(unsigned long type, const char *zValue); SQLITE_API int sqlite3_win32_set_directory16(unsigned long type, const void *zValue); @@ -6519,10 +6519,10 @@ SQLITE_API void *sqlite3_rollback_hook(sqlite3*, void(*)(void *), void*); ** */ SQLITE_API int sqlite3_autovacuum_pages( - sqlite3 *db, - unsigned int(*)(void*,const char*,unsigned int,unsigned int,unsigned int), - void*, - void(*)(void*) + sqlite3 *db, + unsigned int(*)(void*,const char*,unsigned int,unsigned int,unsigned int), + void*, + void(*)(void*) ); @@ -6576,9 +6576,9 @@ SQLITE_API int sqlite3_autovacuum_pages( ** and [sqlite3_preupdate_hook()] interfaces. */ SQLITE_API void *sqlite3_update_hook( - sqlite3*, - void(*)(void *,int ,char const *,char const *,sqlite3_int64), - void* + sqlite3*, + void(*)(void *,int ,char const *,char const *,sqlite3_int64), + void* ); /* @@ -6801,15 +6801,15 @@ SQLITE_API SQLITE_DEPRECATED void sqlite3_soft_heap_limit(int N); ** any errors are encountered while loading the schema. */ SQLITE_API int sqlite3_table_column_metadata( - sqlite3 *db, /* Connection handle */ - const char *zDbName, /* Database name or NULL */ - const char *zTableName, /* Table name */ - const char *zColumnName, /* Column name */ - char const **pzDataType, /* OUTPUT: Declared data type */ - char const **pzCollSeq, /* OUTPUT: Collation sequence name */ - int *pNotNull, /* OUTPUT: True if NOT NULL constraint exists */ - int *pPrimaryKey, /* OUTPUT: True if column part of PK */ - int *pAutoinc /* OUTPUT: True if column is auto-increment */ + sqlite3 *db, /* Connection handle */ + const char *zDbName, /* Database name or NULL */ + const char *zTableName, /* Table name */ + const char *zColumnName, /* Column name */ + char const **pzDataType, /* OUTPUT: Declared data type */ + char const **pzCollSeq, /* OUTPUT: Collation sequence name */ + int *pNotNull, /* OUTPUT: True if NOT NULL constraint exists */ + int *pPrimaryKey, /* OUTPUT: True if column part of PK */ + int *pAutoinc /* OUTPUT: True if column is auto-increment */ ); /* @@ -6857,10 +6857,10 @@ SQLITE_API int sqlite3_table_column_metadata( ** See also the [load_extension() SQL function]. */ SQLITE_API int sqlite3_load_extension( - sqlite3 *db, /* Load the extension into this database connection */ - const char *zFile, /* Name of the shared library containing extension */ - const char *zProc, /* Entry point. Derived from zFile if 0 */ - char **pzErrMsg /* Put error message here if not 0 */ + sqlite3 *db, /* Load the extension into this database connection */ + const char *zFile, /* Name of the shared library containing extension */ + const char *zProc, /* Entry point. Derived from zFile if 0 */ + char **pzErrMsg /* Put error message here if not 0 */ ); /* @@ -6982,41 +6982,41 @@ typedef struct sqlite3_module sqlite3_module; ** any database connection. */ struct sqlite3_module { - int iVersion; - int (*xCreate)(sqlite3*, void *pAux, - int argc, const char *const*argv, - sqlite3_vtab **ppVTab, char**); - int (*xConnect)(sqlite3*, void *pAux, - int argc, const char *const*argv, - sqlite3_vtab **ppVTab, char**); - int (*xBestIndex)(sqlite3_vtab *pVTab, sqlite3_index_info*); - int (*xDisconnect)(sqlite3_vtab *pVTab); - int (*xDestroy)(sqlite3_vtab *pVTab); - int (*xOpen)(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor); - int (*xClose)(sqlite3_vtab_cursor*); - int (*xFilter)(sqlite3_vtab_cursor*, int idxNum, const char *idxStr, - int argc, sqlite3_value **argv); - int (*xNext)(sqlite3_vtab_cursor*); - int (*xEof)(sqlite3_vtab_cursor*); - int (*xColumn)(sqlite3_vtab_cursor*, sqlite3_context*, int); - int (*xRowid)(sqlite3_vtab_cursor*, sqlite3_int64 *pRowid); - int (*xUpdate)(sqlite3_vtab *, int, sqlite3_value **, sqlite3_int64 *); - int (*xBegin)(sqlite3_vtab *pVTab); - int (*xSync)(sqlite3_vtab *pVTab); - int (*xCommit)(sqlite3_vtab *pVTab); - int (*xRollback)(sqlite3_vtab *pVTab); - int (*xFindFunction)(sqlite3_vtab *pVtab, int nArg, const char *zName, - void (**pxFunc)(sqlite3_context*,int,sqlite3_value**), - void **ppArg); - int (*xRename)(sqlite3_vtab *pVtab, const char *zNew); - /* The methods above are in version 1 of the sqlite_module object. Those + int iVersion; + int (*xCreate)(sqlite3*, void *pAux, + int argc, const char *const*argv, + sqlite3_vtab **ppVTab, char**); + int (*xConnect)(sqlite3*, void *pAux, + int argc, const char *const*argv, + sqlite3_vtab **ppVTab, char**); + int (*xBestIndex)(sqlite3_vtab *pVTab, sqlite3_index_info*); + int (*xDisconnect)(sqlite3_vtab *pVTab); + int (*xDestroy)(sqlite3_vtab *pVTab); + int (*xOpen)(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor); + int (*xClose)(sqlite3_vtab_cursor*); + int (*xFilter)(sqlite3_vtab_cursor*, int idxNum, const char *idxStr, + int argc, sqlite3_value **argv); + int (*xNext)(sqlite3_vtab_cursor*); + int (*xEof)(sqlite3_vtab_cursor*); + int (*xColumn)(sqlite3_vtab_cursor*, sqlite3_context*, int); + int (*xRowid)(sqlite3_vtab_cursor*, sqlite3_int64 *pRowid); + int (*xUpdate)(sqlite3_vtab *, int, sqlite3_value **, sqlite3_int64 *); + int (*xBegin)(sqlite3_vtab *pVTab); + int (*xSync)(sqlite3_vtab *pVTab); + int (*xCommit)(sqlite3_vtab *pVTab); + int (*xRollback)(sqlite3_vtab *pVTab); + int (*xFindFunction)(sqlite3_vtab *pVtab, int nArg, const char *zName, + void (**pxFunc)(sqlite3_context*,int,sqlite3_value**), + void **ppArg); + int (*xRename)(sqlite3_vtab *pVtab, const char *zNew); + /* The methods above are in version 1 of the sqlite_module object. Those ** below are for version 2 and greater. */ - int (*xSavepoint)(sqlite3_vtab *pVTab, int); - int (*xRelease)(sqlite3_vtab *pVTab, int); - int (*xRollbackTo)(sqlite3_vtab *pVTab, int); - /* The methods above are in versions 1 and 2 of the sqlite_module object. + int (*xSavepoint)(sqlite3_vtab *pVTab, int); + int (*xRelease)(sqlite3_vtab *pVTab, int); + int (*xRollbackTo)(sqlite3_vtab *pVTab, int); + /* The methods above are in versions 1 and 2 of the sqlite_module object. ** Those below are for version 3 and greater. */ - int (*xShadowName)(const char*); + int (*xShadowName)(const char*); }; /* @@ -7122,35 +7122,35 @@ struct sqlite3_module { ** 3009000. */ struct sqlite3_index_info { - /* Inputs */ - int nConstraint; /* Number of entries in aConstraint */ - struct sqlite3_index_constraint { - int iColumn; /* Column constrained. -1 for ROWID */ - unsigned char op; /* Constraint operator */ - unsigned char usable; /* True if this constraint is usable */ - int iTermOffset; /* Used internally - xBestIndex should ignore */ - } *aConstraint; /* Table of WHERE clause constraints */ - int nOrderBy; /* Number of terms in the ORDER BY clause */ - struct sqlite3_index_orderby { - int iColumn; /* Column number */ - unsigned char desc; /* True for DESC. False for ASC. */ - } *aOrderBy; /* The ORDER BY clause */ - /* Outputs */ - struct sqlite3_index_constraint_usage { - int argvIndex; /* if >0, constraint is part of argv to xFilter */ - unsigned char omit; /* Do not code a test for this constraint */ - } *aConstraintUsage; - int idxNum; /* Number used to identify the index */ - char *idxStr; /* String, possibly obtained from sqlite3_malloc */ - int needToFreeIdxStr; /* Free idxStr using sqlite3_free() if true */ - int orderByConsumed; /* True if output is already ordered */ - double estimatedCost; /* Estimated cost of using this index */ - /* Fields below are only available in SQLite 3.8.2 and later */ - sqlite3_int64 estimatedRows; /* Estimated number of rows returned */ - /* Fields below are only available in SQLite 3.9.0 and later */ - int idxFlags; /* Mask of SQLITE_INDEX_SCAN_* flags */ - /* Fields below are only available in SQLite 3.10.0 and later */ - sqlite3_uint64 colUsed; /* Input: Mask of columns used by statement */ + /* Inputs */ + int nConstraint; /* Number of entries in aConstraint */ + struct sqlite3_index_constraint { + int iColumn; /* Column constrained. -1 for ROWID */ + unsigned char op; /* Constraint operator */ + unsigned char usable; /* True if this constraint is usable */ + int iTermOffset; /* Used internally - xBestIndex should ignore */ + } *aConstraint; /* Table of WHERE clause constraints */ + int nOrderBy; /* Number of terms in the ORDER BY clause */ + struct sqlite3_index_orderby { + int iColumn; /* Column number */ + unsigned char desc; /* True for DESC. False for ASC. */ + } *aOrderBy; /* The ORDER BY clause */ + /* Outputs */ + struct sqlite3_index_constraint_usage { + int argvIndex; /* if >0, constraint is part of argv to xFilter */ + unsigned char omit; /* Do not code a test for this constraint */ + } *aConstraintUsage; + int idxNum; /* Number used to identify the index */ + char *idxStr; /* String, possibly obtained from sqlite3_malloc */ + int needToFreeIdxStr; /* Free idxStr using sqlite3_free() if true */ + int orderByConsumed; /* True if output is already ordered */ + double estimatedCost; /* Estimated cost of using this index */ + /* Fields below are only available in SQLite 3.8.2 and later */ + sqlite3_int64 estimatedRows; /* Estimated number of rows returned */ + /* Fields below are only available in SQLite 3.9.0 and later */ + int idxFlags; /* Mask of SQLITE_INDEX_SCAN_* flags */ + /* Fields below are only available in SQLite 3.10.0 and later */ + sqlite3_uint64 colUsed; /* Input: Mask of columns used by statement */ }; /* @@ -7219,17 +7219,17 @@ struct sqlite3_index_info { ** See also: [sqlite3_drop_modules()] */ SQLITE_API int sqlite3_create_module( - sqlite3 *db, /* SQLite connection to register module with */ - const char *zName, /* Name of the module */ - const sqlite3_module *p, /* Methods for the module */ - void *pClientData /* Client data for xCreate/xConnect */ + sqlite3 *db, /* SQLite connection to register module with */ + const char *zName, /* Name of the module */ + const sqlite3_module *p, /* Methods for the module */ + void *pClientData /* Client data for xCreate/xConnect */ ); SQLITE_API int sqlite3_create_module_v2( - sqlite3 *db, /* SQLite connection to register module with */ - const char *zName, /* Name of the module */ - const sqlite3_module *p, /* Methods for the module */ - void *pClientData, /* Client data for xCreate/xConnect */ - void(*xDestroy)(void*) /* Module destructor function */ + sqlite3 *db, /* SQLite connection to register module with */ + const char *zName, /* Name of the module */ + const sqlite3_module *p, /* Methods for the module */ + void *pClientData, /* Client data for xCreate/xConnect */ + void(*xDestroy)(void*) /* Module destructor function */ ); /* @@ -7245,8 +7245,8 @@ SQLITE_API int sqlite3_create_module_v2( ** See also: [sqlite3_create_module()] */ SQLITE_API int sqlite3_drop_modules( - sqlite3 *db, /* Remove modules from this connection */ - const char **azKeep /* Except, do not remove the ones named here */ + sqlite3 *db, /* Remove modules from this connection */ + const char **azKeep /* Except, do not remove the ones named here */ ); /* @@ -7268,10 +7268,10 @@ SQLITE_API int sqlite3_drop_modules( ** freed by sqlite3_free() and the zErrMsg field will be zeroed. */ struct sqlite3_vtab { - const sqlite3_module *pModule; /* The module for this virtual table */ - int nRef; /* Number of open cursors */ - char *zErrMsg; /* Error message from sqlite3_mprintf() */ - /* Virtual table implementations will typically add additional fields */ + const sqlite3_module *pModule; /* The module for this virtual table */ + int nRef; /* Number of open cursors */ + char *zErrMsg; /* Error message from sqlite3_mprintf() */ + /* Virtual table implementations will typically add additional fields */ }; /* @@ -7292,8 +7292,8 @@ struct sqlite3_vtab { ** are common to all implementations. */ struct sqlite3_vtab_cursor { - sqlite3_vtab *pVtab; /* Virtual table of this cursor */ - /* Virtual table implementations will typically add additional fields */ + sqlite3_vtab *pVtab; /* Virtual table of this cursor */ + /* Virtual table implementations will typically add additional fields */ }; /* @@ -7433,13 +7433,13 @@ typedef struct sqlite3_blob sqlite3_blob; ** [sqlite3_blob_bytes()], [sqlite3_blob_write()]. */ SQLITE_API int sqlite3_blob_open( - sqlite3*, - const char *zDb, - const char *zTable, - const char *zColumn, - sqlite3_int64 iRow, - int flags, - sqlite3_blob **ppBlob + sqlite3*, + const char *zDb, + const char *zTable, + const char *zColumn, + sqlite3_int64 iRow, + int flags, + sqlite3_blob **ppBlob ); /* @@ -7797,15 +7797,15 @@ SQLITE_API void sqlite3_mutex_leave(sqlite3_mutex*); */ typedef struct sqlite3_mutex_methods sqlite3_mutex_methods; struct sqlite3_mutex_methods { - int (*xMutexInit)(void); - int (*xMutexEnd)(void); - sqlite3_mutex *(*xMutexAlloc)(int); - void (*xMutexFree)(sqlite3_mutex *); - void (*xMutexEnter)(sqlite3_mutex *); - int (*xMutexTry)(sqlite3_mutex *); - void (*xMutexLeave)(sqlite3_mutex *); - int (*xMutexHeld)(sqlite3_mutex *); - int (*xMutexNotheld)(sqlite3_mutex *); + int (*xMutexInit)(void); + int (*xMutexEnd)(void); + sqlite3_mutex *(*xMutexAlloc)(int); + void (*xMutexFree)(sqlite3_mutex *); + void (*xMutexEnter)(sqlite3_mutex *); + int (*xMutexTry)(sqlite3_mutex *); + void (*xMutexLeave)(sqlite3_mutex *); + int (*xMutexHeld)(sqlite3_mutex *); + int (*xMutexNotheld)(sqlite3_mutex *); }; /* @@ -8202,10 +8202,10 @@ SQLITE_API char *sqlite3_str_value(sqlite3_str*); */ SQLITE_API int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag); SQLITE_API int sqlite3_status64( - int op, - sqlite3_int64 *pCurrent, - sqlite3_int64 *pHighwater, - int resetFlag + int op, + sqlite3_int64 *pCurrent, + sqlite3_int64 *pHighwater, + int resetFlag ); @@ -8553,8 +8553,8 @@ typedef struct sqlite3_pcache sqlite3_pcache; */ typedef struct sqlite3_pcache_page sqlite3_pcache_page; struct sqlite3_pcache_page { - void *pBuf; /* The content of the page */ - void *pExtra; /* Extra information associated with the page */ + void *pBuf; /* The content of the page */ + void *pExtra; /* Extra information associated with the page */ }; /* @@ -8718,20 +8718,20 @@ struct sqlite3_pcache_page { */ typedef struct sqlite3_pcache_methods2 sqlite3_pcache_methods2; struct sqlite3_pcache_methods2 { - int iVersion; - void *pArg; - int (*xInit)(void*); - void (*xShutdown)(void*); - sqlite3_pcache *(*xCreate)(int szPage, int szExtra, int bPurgeable); - void (*xCachesize)(sqlite3_pcache*, int nCachesize); - int (*xPagecount)(sqlite3_pcache*); - sqlite3_pcache_page *(*xFetch)(sqlite3_pcache*, unsigned key, int createFlag); - void (*xUnpin)(sqlite3_pcache*, sqlite3_pcache_page*, int discard); - void (*xRekey)(sqlite3_pcache*, sqlite3_pcache_page*, - unsigned oldKey, unsigned newKey); - void (*xTruncate)(sqlite3_pcache*, unsigned iLimit); - void (*xDestroy)(sqlite3_pcache*); - void (*xShrink)(sqlite3_pcache*); + int iVersion; + void *pArg; + int (*xInit)(void*); + void (*xShutdown)(void*); + sqlite3_pcache *(*xCreate)(int szPage, int szExtra, int bPurgeable); + void (*xCachesize)(sqlite3_pcache*, int nCachesize); + int (*xPagecount)(sqlite3_pcache*); + sqlite3_pcache_page *(*xFetch)(sqlite3_pcache*, unsigned key, int createFlag); + void (*xUnpin)(sqlite3_pcache*, sqlite3_pcache_page*, int discard); + void (*xRekey)(sqlite3_pcache*, sqlite3_pcache_page*, + unsigned oldKey, unsigned newKey); + void (*xTruncate)(sqlite3_pcache*, unsigned iLimit); + void (*xDestroy)(sqlite3_pcache*); + void (*xShrink)(sqlite3_pcache*); }; /* @@ -8741,17 +8741,17 @@ struct sqlite3_pcache_methods2 { */ typedef struct sqlite3_pcache_methods sqlite3_pcache_methods; struct sqlite3_pcache_methods { - void *pArg; - int (*xInit)(void*); - void (*xShutdown)(void*); - sqlite3_pcache *(*xCreate)(int szPage, int bPurgeable); - void (*xCachesize)(sqlite3_pcache*, int nCachesize); - int (*xPagecount)(sqlite3_pcache*); - void *(*xFetch)(sqlite3_pcache*, unsigned key, int createFlag); - void (*xUnpin)(sqlite3_pcache*, void*, int discard); - void (*xRekey)(sqlite3_pcache*, void*, unsigned oldKey, unsigned newKey); - void (*xTruncate)(sqlite3_pcache*, unsigned iLimit); - void (*xDestroy)(sqlite3_pcache*); + void *pArg; + int (*xInit)(void*); + void (*xShutdown)(void*); + sqlite3_pcache *(*xCreate)(int szPage, int bPurgeable); + void (*xCachesize)(sqlite3_pcache*, int nCachesize); + int (*xPagecount)(sqlite3_pcache*); + void *(*xFetch)(sqlite3_pcache*, unsigned key, int createFlag); + void (*xUnpin)(sqlite3_pcache*, void*, int discard); + void (*xRekey)(sqlite3_pcache*, void*, unsigned oldKey, unsigned newKey); + void (*xTruncate)(sqlite3_pcache*, unsigned iLimit); + void (*xDestroy)(sqlite3_pcache*); }; @@ -8954,10 +8954,10 @@ typedef struct sqlite3_backup sqlite3_backup; ** possible that they return invalid values. */ SQLITE_API sqlite3_backup *sqlite3_backup_init( - sqlite3 *pDest, /* Destination database handle */ - const char *zDestName, /* Destination database name */ - sqlite3 *pSource, /* Source database handle */ - const char *zSourceName /* Source database name */ + sqlite3 *pDest, /* Destination database handle */ + const char *zDestName, /* Destination database name */ + sqlite3 *pSource, /* Source database handle */ + const char *zSourceName /* Source database name */ ); SQLITE_API int sqlite3_backup_step(sqlite3_backup *p, int nPage); SQLITE_API int sqlite3_backup_finish(sqlite3_backup *p); @@ -9080,9 +9080,9 @@ SQLITE_API int sqlite3_backup_pagecount(sqlite3_backup *p); ** SQLITE_LOCKED.)^ */ SQLITE_API int sqlite3_unlock_notify( - sqlite3 *pBlocked, /* Waiting connection */ - void (*xNotify)(void **apArg, int nArg), /* Callback function to invoke */ - void *pNotifyArg /* Argument to pass to xNotify */ + sqlite3 *pBlocked, /* Waiting connection */ + void (*xNotify)(void **apArg, int nArg), /* Callback function to invoke */ + void *pNotifyArg /* Argument to pass to xNotify */ ); @@ -9196,9 +9196,9 @@ SQLITE_API void sqlite3_log(int iErrCode, const char *zFormat, ...); ** overwrite any prior [sqlite3_wal_hook()] settings. */ SQLITE_API void *sqlite3_wal_hook( - sqlite3*, - int(*)(void *,sqlite3*,const char*,int), - void* + sqlite3*, + int(*)(void *,sqlite3*,const char*,int), + void* ); /* @@ -9347,11 +9347,11 @@ SQLITE_API int sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb); ** from SQL. */ SQLITE_API int sqlite3_wal_checkpoint_v2( - sqlite3 *db, /* Database handle */ - const char *zDb, /* Name of attached database (or NULL) */ - int eMode, /* SQLITE_CHECKPOINT_* value */ - int *pnLog, /* OUT: Size of WAL log in frames */ - int *pnCkpt /* OUT: Total number of frames checkpointed */ + sqlite3 *db, /* Database handle */ + const char *zDb, /* Name of attached database (or NULL) */ + int eMode, /* SQLITE_CHECKPOINT_* value */ + int *pnLog, /* OUT: Size of WAL log in frames */ + int *pnCkpt /* OUT: Total number of frames checkpointed */ ); /* @@ -9611,10 +9611,10 @@ SQLITE_API SQLITE_EXPERIMENTAL const char *sqlite3_vtab_collation(sqlite3_index_ ** See also: [sqlite3_stmt_scanstatus_reset()] */ SQLITE_API int sqlite3_stmt_scanstatus( - sqlite3_stmt *pStmt, /* Prepared statement for which info desired */ - int idx, /* Index of loop to report on */ - int iScanStatusOp, /* Information desired. SQLITE_SCANSTAT_* */ - void *pOut /* Result written here */ + sqlite3_stmt *pStmt, /* Prepared statement for which info desired */ + int idx, /* Index of loop to report on */ + int iScanStatusOp, /* Information desired. SQLITE_SCANSTAT_* */ + void *pOut /* Result written here */ ); /* @@ -9755,17 +9755,17 @@ SQLITE_API int sqlite3_db_cacheflush(sqlite3*); */ #if defined(SQLITE_ENABLE_PREUPDATE_HOOK) SQLITE_API void *sqlite3_preupdate_hook( - sqlite3 *db, - void(*xPreUpdate)( - void *pCtx, /* Copy of third arg to preupdate_hook() */ - sqlite3 *db, /* Database handle */ - int op, /* SQLITE_UPDATE, DELETE or INSERT */ - char const *zDb, /* Database name */ - char const *zName, /* Table name */ - sqlite3_int64 iKey1, /* Rowid of row about to be deleted/updated */ - sqlite3_int64 iKey2 /* New rowid value (for a rowid UPDATE) */ - ), - void* + sqlite3 *db, + void(*xPreUpdate)( + void *pCtx, /* Copy of third arg to preupdate_hook() */ + sqlite3 *db, /* Database handle */ + int op, /* SQLITE_UPDATE, DELETE or INSERT */ + char const *zDb, /* Database name */ + char const *zName, /* Table name */ + sqlite3_int64 iKey1, /* Rowid of row about to be deleted/updated */ + sqlite3_int64 iKey2 /* New rowid value (for a rowid UPDATE) */ + ), + void* ); SQLITE_API int sqlite3_preupdate_old(sqlite3 *, int, sqlite3_value **); SQLITE_API int sqlite3_preupdate_count(sqlite3 *); @@ -9808,7 +9808,7 @@ SQLITE_API int sqlite3_system_errno(sqlite3*); ** the most recent version. */ typedef struct sqlite3_snapshot { - unsigned char hidden[48]; + unsigned char hidden[48]; } sqlite3_snapshot; /* @@ -9855,9 +9855,9 @@ typedef struct sqlite3_snapshot { ** [SQLITE_ENABLE_SNAPSHOT] compile-time option is used. */ SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_get( - sqlite3 *db, - const char *zSchema, - sqlite3_snapshot **ppSnapshot + sqlite3 *db, + const char *zSchema, + sqlite3_snapshot **ppSnapshot ); /* @@ -9904,9 +9904,9 @@ SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_get( ** [SQLITE_ENABLE_SNAPSHOT] compile-time option is used. */ SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_open( - sqlite3 *db, - const char *zSchema, - sqlite3_snapshot *pSnapshot + sqlite3 *db, + const char *zSchema, + sqlite3_snapshot *pSnapshot ); /* @@ -9948,8 +9948,8 @@ SQLITE_API SQLITE_EXPERIMENTAL void sqlite3_snapshot_free(sqlite3_snapshot*); ** [SQLITE_ENABLE_SNAPSHOT] option. */ SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_cmp( - sqlite3_snapshot *p1, - sqlite3_snapshot *p2 + sqlite3_snapshot *p1, + sqlite3_snapshot *p2 ); /* @@ -10014,10 +10014,10 @@ SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_recover(sqlite3 *db, const c ** [SQLITE_OMIT_DESERIALIZE] option. */ SQLITE_API unsigned char *sqlite3_serialize( - sqlite3 *db, /* The database connection */ - const char *zSchema, /* Which DB to serialize. ex: "main", "temp", ... */ - sqlite3_int64 *piSize, /* Write size of the DB here, if not NULL */ - unsigned int mFlags /* Zero or more SQLITE_SERIALIZE_* flags */ + sqlite3 *db, /* The database connection */ + const char *zSchema, /* Which DB to serialize. ex: "main", "temp", ... */ + sqlite3_int64 *piSize, /* Write size of the DB here, if not NULL */ + unsigned int mFlags /* Zero or more SQLITE_SERIALIZE_* flags */ ); /* @@ -10070,12 +10070,12 @@ SQLITE_API unsigned char *sqlite3_serialize( ** [SQLITE_OMIT_DESERIALIZE] option. */ SQLITE_API int sqlite3_deserialize( - sqlite3 *db, /* The database connection */ - const char *zSchema, /* Which DB to reopen with the deserialization */ - unsigned char *pData, /* The serialized database content */ - sqlite3_int64 szDb, /* Number bytes in the deserialization */ - sqlite3_int64 szBuf, /* Total size of buffer pData[] */ - unsigned mFlags /* Zero or more SQLITE_DESERIALIZE_* flags */ + sqlite3 *db, /* The database connection */ + const char *zSchema, /* Which DB to reopen with the deserialization */ + unsigned char *pData, /* The serialized database content */ + sqlite3_int64 szDb, /* Number bytes in the deserialization */ + sqlite3_int64 szBuf, /* Total size of buffer pData[] */ + unsigned mFlags /* Zero or more SQLITE_DESERIALIZE_* flags */ ); /* @@ -10145,9 +10145,9 @@ typedef struct sqlite3_rtree_query_info sqlite3_rtree_query_info; ** SQLITE_RTREE_INT_ONLY compile-time option. */ #ifdef SQLITE_RTREE_INT_ONLY -typedef sqlite3_int64 sqlite3_rtree_dbl; + typedef sqlite3_int64 sqlite3_rtree_dbl; #else -typedef double sqlite3_rtree_dbl; + typedef double sqlite3_rtree_dbl; #endif /* @@ -10157,10 +10157,10 @@ typedef double sqlite3_rtree_dbl; ** SELECT ... FROM WHERE MATCH $zGeom(... params ...) */ SQLITE_API int sqlite3_rtree_geometry_callback( - sqlite3 *db, - const char *zGeom, - int (*xGeom)(sqlite3_rtree_geometry*, int, sqlite3_rtree_dbl*,int*), - void *pContext + sqlite3 *db, + const char *zGeom, + int (*xGeom)(sqlite3_rtree_geometry*, int, sqlite3_rtree_dbl*,int*), + void *pContext ); @@ -10169,11 +10169,11 @@ SQLITE_API int sqlite3_rtree_geometry_callback( ** argument to callbacks registered using rtree_geometry_callback(). */ struct sqlite3_rtree_geometry { - void *pContext; /* Copy of pContext passed to s_r_g_c() */ - int nParam; /* Size of array aParam[] */ - sqlite3_rtree_dbl *aParam; /* Parameters passed to SQL geom function */ - void *pUser; /* Callback implementation user data */ - void (*xDelUser)(void *); /* Called by SQLite to clean up pUser */ + void *pContext; /* Copy of pContext passed to s_r_g_c() */ + int nParam; /* Size of array aParam[] */ + sqlite3_rtree_dbl *aParam; /* Parameters passed to SQL geom function */ + void *pUser; /* Callback implementation user data */ + void (*xDelUser)(void *); /* Called by SQLite to clean up pUser */ }; /* @@ -10183,11 +10183,11 @@ struct sqlite3_rtree_geometry { ** SELECT ... FROM WHERE MATCH $zQueryFunc(... params ...) */ SQLITE_API int sqlite3_rtree_query_callback( - sqlite3 *db, - const char *zQueryFunc, - int (*xQueryFunc)(sqlite3_rtree_query_info*), - void *pContext, - void (*xDestructor)(void*) + sqlite3 *db, + const char *zQueryFunc, + int (*xQueryFunc)(sqlite3_rtree_query_info*), + void *pContext, + void (*xDestructor)(void*) ); @@ -10201,23 +10201,23 @@ SQLITE_API int sqlite3_rtree_query_callback( ** sqlite3_rtree_geometry. */ struct sqlite3_rtree_query_info { - void *pContext; /* pContext from when function registered */ - int nParam; /* Number of function parameters */ - sqlite3_rtree_dbl *aParam; /* value of function parameters */ - void *pUser; /* callback can use this, if desired */ - void (*xDelUser)(void*); /* function to free pUser */ - sqlite3_rtree_dbl *aCoord; /* Coordinates of node or entry to check */ - unsigned int *anQueue; /* Number of pending entries in the queue */ - int nCoord; /* Number of coordinates */ - int iLevel; /* Level of current node or entry */ - int mxLevel; /* The largest iLevel value in the tree */ - sqlite3_int64 iRowid; /* Rowid for current entry */ - sqlite3_rtree_dbl rParentScore; /* Score of parent node */ - int eParentWithin; /* Visibility of parent node */ - int eWithin; /* OUT: Visibility */ - sqlite3_rtree_dbl rScore; /* OUT: Write the score here */ - /* The following fields are only available in 3.8.11 and later */ - sqlite3_value **apSqlParam; /* Original SQL values of parameters */ + void *pContext; /* pContext from when function registered */ + int nParam; /* Number of function parameters */ + sqlite3_rtree_dbl *aParam; /* value of function parameters */ + void *pUser; /* callback can use this, if desired */ + void (*xDelUser)(void*); /* function to free pUser */ + sqlite3_rtree_dbl *aCoord; /* Coordinates of node or entry to check */ + unsigned int *anQueue; /* Number of pending entries in the queue */ + int nCoord; /* Number of coordinates */ + int iLevel; /* Level of current node or entry */ + int mxLevel; /* The largest iLevel value in the tree */ + sqlite3_int64 iRowid; /* Rowid for current entry */ + sqlite3_rtree_dbl rParentScore; /* Score of parent node */ + int eParentWithin; /* Visibility of parent node */ + int eWithin; /* OUT: Visibility */ + sqlite3_rtree_dbl rScore; /* OUT: Write the score here */ + /* The following fields are only available in 3.8.11 and later */ + sqlite3_value **apSqlParam; /* Original SQL values of parameters */ }; /* @@ -10296,9 +10296,9 @@ typedef struct sqlite3_changeset_iter sqlite3_changeset_iter; ** to the database when the session object is created. */ SQLITE_API int sqlite3session_create( - sqlite3 *db, /* Database handle */ - const char *zDb, /* Name of db (e.g. "main") */ - sqlite3_session **ppSession /* OUT: New session object */ + sqlite3 *db, /* Database handle */ + const char *zDb, /* Name of db (e.g. "main") */ + sqlite3_session **ppSession /* OUT: New session object */ ); /* @@ -10458,8 +10458,8 @@ SQLITE_API int sqlite3session_indirect(sqlite3_session *pSession, int bIndirect) ** sqlite_stat1 table that are part of a changeset or patchset. */ SQLITE_API int sqlite3session_attach( - sqlite3_session *pSession, /* Session object */ - const char *zTab /* Table name */ + sqlite3_session *pSession, /* Session object */ + const char *zTab /* Table name */ ); /* @@ -10473,12 +10473,12 @@ SQLITE_API int sqlite3session_attach( ** attached, xFilter will not be called again. */ SQLITE_API void sqlite3session_table_filter( - sqlite3_session *pSession, /* Session object */ - int(*xFilter)( - void *pCtx, /* Copy of third arg to _filter_table() */ - const char *zTab /* Table name */ - ), - void *pCtx /* First argument passed to xFilter */ + sqlite3_session *pSession, /* Session object */ + int(*xFilter)( + void *pCtx, /* Copy of third arg to _filter_table() */ + const char *zTab /* Table name */ + ), + void *pCtx /* First argument passed to xFilter */ ); /* @@ -10587,9 +10587,9 @@ SQLITE_API void sqlite3session_table_filter( ** resulting changeset will contain an UPDATE change that updates both fields. */ SQLITE_API int sqlite3session_changeset( - sqlite3_session *pSession, /* Session object */ - int *pnChangeset, /* OUT: Size of buffer at *ppChangeset */ - void **ppChangeset /* OUT: Buffer containing changeset */ + sqlite3_session *pSession, /* Session object */ + int *pnChangeset, /* OUT: Size of buffer at *ppChangeset */ + void **ppChangeset /* OUT: Buffer containing changeset */ ); /* @@ -10666,10 +10666,10 @@ SQLITE_API sqlite3_int64 sqlite3session_changeset_size(sqlite3_session *pSession ** sqlite3_free(). */ SQLITE_API int sqlite3session_diff( - sqlite3_session *pSession, - const char *zFromDb, - const char *zTbl, - char **pzErrMsg + sqlite3_session *pSession, + const char *zFromDb, + const char *zTbl, + char **pzErrMsg ); @@ -10703,9 +10703,9 @@ SQLITE_API int sqlite3session_diff( ** they were attached to the session object). */ SQLITE_API int sqlite3session_patchset( - sqlite3_session *pSession, /* Session object */ - int *pnPatchset, /* OUT: Size of buffer at *ppPatchset */ - void **ppPatchset /* OUT: Buffer containing patchset */ + sqlite3_session *pSession, /* Session object */ + int *pnPatchset, /* OUT: Size of buffer at *ppPatchset */ + void **ppPatchset /* OUT: Buffer containing patchset */ ); /* @@ -10775,15 +10775,15 @@ SQLITE_API sqlite3_int64 sqlite3session_memory_used(sqlite3_session *pSession); ** and therefore subject to change. */ SQLITE_API int sqlite3changeset_start( - sqlite3_changeset_iter **pp, /* OUT: New changeset iterator handle */ - int nChangeset, /* Size of changeset blob in bytes */ - void *pChangeset /* Pointer to blob containing changeset */ + sqlite3_changeset_iter **pp, /* OUT: New changeset iterator handle */ + int nChangeset, /* Size of changeset blob in bytes */ + void *pChangeset /* Pointer to blob containing changeset */ ); SQLITE_API int sqlite3changeset_start_v2( - sqlite3_changeset_iter **pp, /* OUT: New changeset iterator handle */ - int nChangeset, /* Size of changeset blob in bytes */ - void *pChangeset, /* Pointer to blob containing changeset */ - int flags /* SESSION_CHANGESETSTART_* flags */ + sqlite3_changeset_iter **pp, /* OUT: New changeset iterator handle */ + int nChangeset, /* Size of changeset blob in bytes */ + void *pChangeset, /* Pointer to blob containing changeset */ + int flags /* SESSION_CHANGESETSTART_* flags */ ); /* @@ -10858,11 +10858,11 @@ SQLITE_API int sqlite3changeset_next(sqlite3_changeset_iter *pIter); ** be trusted in this case. */ SQLITE_API int sqlite3changeset_op( - sqlite3_changeset_iter *pIter, /* Iterator object */ - const char **pzTab, /* OUT: Pointer to table name */ - int *pnCol, /* OUT: Number of columns in table */ - int *pOp, /* OUT: SQLITE_INSERT, DELETE or UPDATE */ - int *pbIndirect /* OUT: True for an 'indirect' change */ + sqlite3_changeset_iter *pIter, /* Iterator object */ + const char **pzTab, /* OUT: Pointer to table name */ + int *pnCol, /* OUT: Number of columns in table */ + int *pOp, /* OUT: SQLITE_INSERT, DELETE or UPDATE */ + int *pbIndirect /* OUT: True for an 'indirect' change */ ); /* @@ -10892,9 +10892,9 @@ SQLITE_API int sqlite3changeset_op( ** above. */ SQLITE_API int sqlite3changeset_pk( - sqlite3_changeset_iter *pIter, /* Iterator object */ - unsigned char **pabPK, /* OUT: Array of boolean - true for PK cols */ - int *pnCol /* OUT: Number of entries in output array */ + sqlite3_changeset_iter *pIter, /* Iterator object */ + unsigned char **pabPK, /* OUT: Array of boolean - true for PK cols */ + int *pnCol /* OUT: Number of entries in output array */ ); /* @@ -10923,9 +10923,9 @@ SQLITE_API int sqlite3changeset_pk( ** is returned and *ppValue is set to NULL. */ SQLITE_API int sqlite3changeset_old( - sqlite3_changeset_iter *pIter, /* Changeset iterator */ - int iVal, /* Column number */ - sqlite3_value **ppValue /* OUT: Old value (or NULL pointer) */ + sqlite3_changeset_iter *pIter, /* Changeset iterator */ + int iVal, /* Column number */ + sqlite3_value **ppValue /* OUT: Old value (or NULL pointer) */ ); /* @@ -10957,9 +10957,9 @@ SQLITE_API int sqlite3changeset_old( ** is returned and *ppValue is set to NULL. */ SQLITE_API int sqlite3changeset_new( - sqlite3_changeset_iter *pIter, /* Changeset iterator */ - int iVal, /* Column number */ - sqlite3_value **ppValue /* OUT: New value (or NULL pointer) */ + sqlite3_changeset_iter *pIter, /* Changeset iterator */ + int iVal, /* Column number */ + sqlite3_value **ppValue /* OUT: New value (or NULL pointer) */ ); /* @@ -10985,9 +10985,9 @@ SQLITE_API int sqlite3changeset_new( ** is returned and *ppValue is set to NULL. */ SQLITE_API int sqlite3changeset_conflict( - sqlite3_changeset_iter *pIter, /* Changeset iterator */ - int iVal, /* Column number */ - sqlite3_value **ppValue /* OUT: Value from conflicting row */ + sqlite3_changeset_iter *pIter, /* Changeset iterator */ + int iVal, /* Column number */ + sqlite3_value **ppValue /* OUT: Value from conflicting row */ ); /* @@ -11002,8 +11002,8 @@ SQLITE_API int sqlite3changeset_conflict( ** In all other cases this function returns SQLITE_MISUSE. */ SQLITE_API int sqlite3changeset_fk_conflicts( - sqlite3_changeset_iter *pIter, /* Changeset iterator */ - int *pnOut /* OUT: Number of FK violations */ + sqlite3_changeset_iter *pIter, /* Changeset iterator */ + int *pnOut /* OUT: Number of FK violations */ ); @@ -11068,8 +11068,8 @@ SQLITE_API int sqlite3changeset_finalize(sqlite3_changeset_iter *pIter); ** changeset. If it is not, the results are undefined. */ SQLITE_API int sqlite3changeset_invert( - int nIn, const void *pIn, /* Input changeset */ - int *pnOut, void **ppOut /* OUT: Inverse of input */ + int nIn, const void *pIn, /* Input changeset */ + int *pnOut, void **ppOut /* OUT: Inverse of input */ ); /* @@ -11099,12 +11099,12 @@ SQLITE_API int sqlite3changeset_invert( ** Refer to the sqlite3_changegroup documentation below for details. */ SQLITE_API int sqlite3changeset_concat( - int nA, /* Number of bytes in buffer pA */ - void *pA, /* Pointer to buffer containing changeset A */ - int nB, /* Number of bytes in buffer pB */ - void *pB, /* Pointer to buffer containing changeset B */ - int *pnOut, /* OUT: Number of bytes in output changeset */ - void **ppOut /* OUT: Buffer containing output changeset */ + int nA, /* Number of bytes in buffer pA */ + void *pA, /* Pointer to buffer containing changeset A */ + int nB, /* Number of bytes in buffer pB */ + void *pB, /* Pointer to buffer containing changeset B */ + int *pnOut, /* OUT: Number of bytes in output changeset */ + void **ppOut /* OUT: Buffer containing output changeset */ ); @@ -11258,9 +11258,9 @@ SQLITE_API int sqlite3changegroup_add(sqlite3_changegroup*, int nData, void *pDa ** call to sqlite3_free(). */ SQLITE_API int sqlite3changegroup_output( - sqlite3_changegroup*, - int *pnData, /* OUT: Size of output buffer in bytes */ - void **ppData /* OUT: Pointer to output buffer */ + sqlite3_changegroup*, + int *pnData, /* OUT: Size of output buffer in bytes */ + void **ppData /* OUT: Pointer to output buffer */ ); /* @@ -11428,36 +11428,36 @@ SQLITE_API void sqlite3changegroup_delete(sqlite3_changegroup*); ** and therefore subject to change. */ SQLITE_API int sqlite3changeset_apply( - sqlite3 *db, /* Apply change to "main" db of this handle */ - int nChangeset, /* Size of changeset in bytes */ - void *pChangeset, /* Changeset blob */ - int(*xFilter)( - void *pCtx, /* Copy of sixth arg to _apply() */ - const char *zTab /* Table name */ - ), - int(*xConflict)( - void *pCtx, /* Copy of sixth arg to _apply() */ - int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */ - sqlite3_changeset_iter *p /* Handle describing change and conflict */ - ), - void *pCtx /* First argument passed to xConflict */ + sqlite3 *db, /* Apply change to "main" db of this handle */ + int nChangeset, /* Size of changeset in bytes */ + void *pChangeset, /* Changeset blob */ + int(*xFilter)( + void *pCtx, /* Copy of sixth arg to _apply() */ + const char *zTab /* Table name */ + ), + int(*xConflict)( + void *pCtx, /* Copy of sixth arg to _apply() */ + int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */ + sqlite3_changeset_iter *p /* Handle describing change and conflict */ + ), + void *pCtx /* First argument passed to xConflict */ ); SQLITE_API int sqlite3changeset_apply_v2( - sqlite3 *db, /* Apply change to "main" db of this handle */ - int nChangeset, /* Size of changeset in bytes */ - void *pChangeset, /* Changeset blob */ - int(*xFilter)( - void *pCtx, /* Copy of sixth arg to _apply() */ - const char *zTab /* Table name */ - ), - int(*xConflict)( - void *pCtx, /* Copy of sixth arg to _apply() */ - int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */ - sqlite3_changeset_iter *p /* Handle describing change and conflict */ - ), - void *pCtx, /* First argument passed to xConflict */ - void **ppRebase, int *pnRebase, /* OUT: Rebase data */ - int flags /* SESSION_CHANGESETAPPLY_* flags */ + sqlite3 *db, /* Apply change to "main" db of this handle */ + int nChangeset, /* Size of changeset in bytes */ + void *pChangeset, /* Changeset blob */ + int(*xFilter)( + void *pCtx, /* Copy of sixth arg to _apply() */ + const char *zTab /* Table name */ + ), + int(*xConflict)( + void *pCtx, /* Copy of sixth arg to _apply() */ + int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */ + sqlite3_changeset_iter *p /* Handle describing change and conflict */ + ), + void *pCtx, /* First argument passed to xConflict */ + void **ppRebase, int *pnRebase, /* OUT: Rebase data */ + int flags /* SESSION_CHANGESETAPPLY_* flags */ ); /* @@ -11701,8 +11701,8 @@ SQLITE_API int sqlite3rebaser_create(sqlite3_rebaser **ppNew); ** sqlite3changeset_apply_v2(). */ SQLITE_API int sqlite3rebaser_configure( - sqlite3_rebaser*, - int nRebase, const void *pRebase + sqlite3_rebaser*, + int nRebase, const void *pRebase ); /* @@ -11720,9 +11720,9 @@ SQLITE_API int sqlite3rebaser_configure( ** are set to zero and an SQLite error code returned. */ SQLITE_API int sqlite3rebaser_rebase( - sqlite3_rebaser*, - int nIn, const void *pIn, - int *pnOut, void **ppOut + sqlite3_rebaser*, + int nIn, const void *pIn, + int *pnOut, void **ppOut ); /* @@ -11826,71 +11826,71 @@ SQLITE_API void sqlite3rebaser_delete(sqlite3_rebaser *p); ** no guarantees are made as to the size of the chunks of data returned. */ SQLITE_API int sqlite3changeset_apply_strm( - sqlite3 *db, /* Apply change to "main" db of this handle */ - int (*xInput)(void *pIn, void *pData, int *pnData), /* Input function */ - void *pIn, /* First arg for xInput */ - int(*xFilter)( - void *pCtx, /* Copy of sixth arg to _apply() */ - const char *zTab /* Table name */ - ), - int(*xConflict)( - void *pCtx, /* Copy of sixth arg to _apply() */ - int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */ - sqlite3_changeset_iter *p /* Handle describing change and conflict */ - ), - void *pCtx /* First argument passed to xConflict */ + sqlite3 *db, /* Apply change to "main" db of this handle */ + int (*xInput)(void *pIn, void *pData, int *pnData), /* Input function */ + void *pIn, /* First arg for xInput */ + int(*xFilter)( + void *pCtx, /* Copy of sixth arg to _apply() */ + const char *zTab /* Table name */ + ), + int(*xConflict)( + void *pCtx, /* Copy of sixth arg to _apply() */ + int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */ + sqlite3_changeset_iter *p /* Handle describing change and conflict */ + ), + void *pCtx /* First argument passed to xConflict */ ); SQLITE_API int sqlite3changeset_apply_v2_strm( - sqlite3 *db, /* Apply change to "main" db of this handle */ - int (*xInput)(void *pIn, void *pData, int *pnData), /* Input function */ - void *pIn, /* First arg for xInput */ - int(*xFilter)( - void *pCtx, /* Copy of sixth arg to _apply() */ - const char *zTab /* Table name */ - ), - int(*xConflict)( - void *pCtx, /* Copy of sixth arg to _apply() */ - int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */ - sqlite3_changeset_iter *p /* Handle describing change and conflict */ - ), - void *pCtx, /* First argument passed to xConflict */ - void **ppRebase, int *pnRebase, - int flags + sqlite3 *db, /* Apply change to "main" db of this handle */ + int (*xInput)(void *pIn, void *pData, int *pnData), /* Input function */ + void *pIn, /* First arg for xInput */ + int(*xFilter)( + void *pCtx, /* Copy of sixth arg to _apply() */ + const char *zTab /* Table name */ + ), + int(*xConflict)( + void *pCtx, /* Copy of sixth arg to _apply() */ + int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */ + sqlite3_changeset_iter *p /* Handle describing change and conflict */ + ), + void *pCtx, /* First argument passed to xConflict */ + void **ppRebase, int *pnRebase, + int flags ); SQLITE_API int sqlite3changeset_concat_strm( - int (*xInputA)(void *pIn, void *pData, int *pnData), - void *pInA, - int (*xInputB)(void *pIn, void *pData, int *pnData), - void *pInB, - int (*xOutput)(void *pOut, const void *pData, int nData), - void *pOut + int (*xInputA)(void *pIn, void *pData, int *pnData), + void *pInA, + int (*xInputB)(void *pIn, void *pData, int *pnData), + void *pInB, + int (*xOutput)(void *pOut, const void *pData, int nData), + void *pOut ); SQLITE_API int sqlite3changeset_invert_strm( - int (*xInput)(void *pIn, void *pData, int *pnData), - void *pIn, - int (*xOutput)(void *pOut, const void *pData, int nData), - void *pOut + int (*xInput)(void *pIn, void *pData, int *pnData), + void *pIn, + int (*xOutput)(void *pOut, const void *pData, int nData), + void *pOut ); SQLITE_API int sqlite3changeset_start_strm( - sqlite3_changeset_iter **pp, - int (*xInput)(void *pIn, void *pData, int *pnData), - void *pIn + sqlite3_changeset_iter **pp, + int (*xInput)(void *pIn, void *pData, int *pnData), + void *pIn ); SQLITE_API int sqlite3changeset_start_v2_strm( - sqlite3_changeset_iter **pp, - int (*xInput)(void *pIn, void *pData, int *pnData), - void *pIn, - int flags + sqlite3_changeset_iter **pp, + int (*xInput)(void *pIn, void *pData, int *pnData), + void *pIn, + int flags ); SQLITE_API int sqlite3session_changeset_strm( - sqlite3_session *pSession, - int (*xOutput)(void *pOut, const void *pData, int nData), - void *pOut + sqlite3_session *pSession, + int (*xOutput)(void *pOut, const void *pData, int nData), + void *pOut ); SQLITE_API int sqlite3session_patchset_strm( - sqlite3_session *pSession, - int (*xOutput)(void *pOut, const void *pData, int nData), - void *pOut + sqlite3_session *pSession, + int (*xOutput)(void *pOut, const void *pData, int nData), + void *pOut ); SQLITE_API int sqlite3changegroup_add_strm(sqlite3_changegroup*, int (*xInput)(void *pIn, void *pData, int *pnData), @@ -11901,11 +11901,11 @@ SQLITE_API int sqlite3changegroup_output_strm(sqlite3_changegroup*, void *pOut ); SQLITE_API int sqlite3rebaser_rebase_strm( - sqlite3_rebaser *pRebaser, - int (*xInput)(void *pIn, void *pData, int *pnData), - void *pIn, - int (*xOutput)(void *pOut, const void *pData, int nData), - void *pOut + sqlite3_rebaser *pRebaser, + int (*xInput)(void *pIn, void *pData, int *pnData), + void *pIn, + int (*xOutput)(void *pOut, const void *pData, int nData), + void *pOut ); /* @@ -11999,16 +11999,16 @@ typedef struct Fts5Context Fts5Context; typedef struct Fts5PhraseIter Fts5PhraseIter; typedef void (*fts5_extension_function)( - const Fts5ExtensionApi *pApi, /* API offered by current FTS version */ - Fts5Context *pFts, /* First arg to pass to pApi functions */ - sqlite3_context *pCtx, /* Context for returning result/error */ - int nVal, /* Number of values in apVal[] array */ - sqlite3_value **apVal /* Array of trailing arguments */ + const Fts5ExtensionApi *pApi, /* API offered by current FTS version */ + Fts5Context *pFts, /* First arg to pass to pApi functions */ + sqlite3_context *pCtx, /* Context for returning result/error */ + int nVal, /* Number of values in apVal[] array */ + sqlite3_value **apVal /* Array of trailing arguments */ ); struct Fts5PhraseIter { - const unsigned char *a; - const unsigned char *b; + const unsigned char *a; + const unsigned char *b; }; /* @@ -12223,41 +12223,41 @@ struct Fts5PhraseIter { ** See xPhraseFirstColumn above. */ struct Fts5ExtensionApi { - int iVersion; /* Currently always set to 3 */ + int iVersion; /* Currently always set to 3 */ - void *(*xUserData)(Fts5Context*); + void *(*xUserData)(Fts5Context*); - int (*xColumnCount)(Fts5Context*); - int (*xRowCount)(Fts5Context*, sqlite3_int64 *pnRow); - int (*xColumnTotalSize)(Fts5Context*, int iCol, sqlite3_int64 *pnToken); + int (*xColumnCount)(Fts5Context*); + int (*xRowCount)(Fts5Context*, sqlite3_int64 *pnRow); + int (*xColumnTotalSize)(Fts5Context*, int iCol, sqlite3_int64 *pnToken); - int (*xTokenize)(Fts5Context*, - const char *pText, int nText, /* Text to tokenize */ - void *pCtx, /* Context passed to xToken() */ - int (*xToken)(void*, int, const char*, int, int, int) /* Callback */ - ); + int (*xTokenize)(Fts5Context*, + const char *pText, int nText, /* Text to tokenize */ + void *pCtx, /* Context passed to xToken() */ + int (*xToken)(void*, int, const char*, int, int, int) /* Callback */ + ); - int (*xPhraseCount)(Fts5Context*); - int (*xPhraseSize)(Fts5Context*, int iPhrase); + int (*xPhraseCount)(Fts5Context*); + int (*xPhraseSize)(Fts5Context*, int iPhrase); - int (*xInstCount)(Fts5Context*, int *pnInst); - int (*xInst)(Fts5Context*, int iIdx, int *piPhrase, int *piCol, int *piOff); + int (*xInstCount)(Fts5Context*, int *pnInst); + int (*xInst)(Fts5Context*, int iIdx, int *piPhrase, int *piCol, int *piOff); - sqlite3_int64 (*xRowid)(Fts5Context*); - int (*xColumnText)(Fts5Context*, int iCol, const char **pz, int *pn); - int (*xColumnSize)(Fts5Context*, int iCol, int *pnToken); + sqlite3_int64 (*xRowid)(Fts5Context*); + int (*xColumnText)(Fts5Context*, int iCol, const char **pz, int *pn); + int (*xColumnSize)(Fts5Context*, int iCol, int *pnToken); - int (*xQueryPhrase)(Fts5Context*, int iPhrase, void *pUserData, - int(*)(const Fts5ExtensionApi*,Fts5Context*,void*) - ); - int (*xSetAuxdata)(Fts5Context*, void *pAux, void(*xDelete)(void*)); - void *(*xGetAuxdata)(Fts5Context*, int bClear); + int (*xQueryPhrase)(Fts5Context*, int iPhrase, void *pUserData, + int(*)(const Fts5ExtensionApi*,Fts5Context*,void*) + ); + int (*xSetAuxdata)(Fts5Context*, void *pAux, void(*xDelete)(void*)); + void *(*xGetAuxdata)(Fts5Context*, int bClear); - int (*xPhraseFirst)(Fts5Context*, int iPhrase, Fts5PhraseIter*, int*, int*); - void (*xPhraseNext)(Fts5Context*, Fts5PhraseIter*, int *piCol, int *piOff); + int (*xPhraseFirst)(Fts5Context*, int iPhrase, Fts5PhraseIter*, int*, int*); + void (*xPhraseNext)(Fts5Context*, Fts5PhraseIter*, int *piCol, int *piOff); - int (*xPhraseFirstColumn)(Fts5Context*, int iPhrase, Fts5PhraseIter*, int*); - void (*xPhraseNextColumn)(Fts5Context*, Fts5PhraseIter*, int *piCol); + int (*xPhraseFirstColumn)(Fts5Context*, int iPhrase, Fts5PhraseIter*, int*); + void (*xPhraseNextColumn)(Fts5Context*, Fts5PhraseIter*, int *piCol); }; /* @@ -12459,21 +12459,21 @@ struct Fts5ExtensionApi { typedef struct Fts5Tokenizer Fts5Tokenizer; typedef struct fts5_tokenizer fts5_tokenizer; struct fts5_tokenizer { - int (*xCreate)(void*, const char **azArg, int nArg, Fts5Tokenizer **ppOut); - void (*xDelete)(Fts5Tokenizer*); - int (*xTokenize)(Fts5Tokenizer*, - void *pCtx, - int flags, /* Mask of FTS5_TOKENIZE_* flags */ - const char *pText, int nText, - int (*xToken)( - void *pCtx, /* Copy of 2nd argument to xTokenize() */ - int tflags, /* Mask of FTS5_TOKEN_* flags */ - const char *pToken, /* Pointer to buffer containing token */ - int nToken, /* Size of token in bytes */ - int iStart, /* Byte offset of token within input text */ - int iEnd /* Byte offset of end of token within input text */ - ) - ); + int (*xCreate)(void*, const char **azArg, int nArg, Fts5Tokenizer **ppOut); + void (*xDelete)(Fts5Tokenizer*); + int (*xTokenize)(Fts5Tokenizer*, + void *pCtx, + int flags, /* Mask of FTS5_TOKENIZE_* flags */ + const char *pText, int nText, + int (*xToken)( + void *pCtx, /* Copy of 2nd argument to xTokenize() */ + int tflags, /* Mask of FTS5_TOKEN_* flags */ + const char *pToken, /* Pointer to buffer containing token */ + int nToken, /* Size of token in bytes */ + int iStart, /* Byte offset of token within input text */ + int iEnd /* Byte offset of end of token within input text */ + ) + ); }; /* Flags that may be passed as the third argument to xTokenize() */ @@ -12495,33 +12495,33 @@ struct fts5_tokenizer { */ typedef struct fts5_api fts5_api; struct fts5_api { - int iVersion; /* Currently always set to 2 */ - - /* Create a new tokenizer */ - int (*xCreateTokenizer)( - fts5_api *pApi, - const char *zName, - void *pContext, - fts5_tokenizer *pTokenizer, - void (*xDestroy)(void*) - ); - - /* Find an existing tokenizer */ - int (*xFindTokenizer)( - fts5_api *pApi, - const char *zName, - void **ppContext, - fts5_tokenizer *pTokenizer - ); - - /* Create a new auxiliary function */ - int (*xCreateFunction)( - fts5_api *pApi, - const char *zName, - void *pContext, - fts5_extension_function xFunction, - void (*xDestroy)(void*) - ); + int iVersion; /* Currently always set to 2 */ + + /* Create a new tokenizer */ + int (*xCreateTokenizer)( + fts5_api *pApi, + const char *zName, + void *pContext, + fts5_tokenizer *pTokenizer, + void (*xDestroy)(void*) + ); + + /* Find an existing tokenizer */ + int (*xFindTokenizer)( + fts5_api *pApi, + const char *zName, + void **ppContext, + fts5_tokenizer *pTokenizer + ); + + /* Create a new auxiliary function */ + int (*xCreateFunction)( + fts5_api *pApi, + const char *zName, + void *pContext, + fts5_extension_function xFunction, + void (*xDestroy)(void*) + ); }; /* diff --git a/mock/sqlite/include/sqlite3ext.h b/mock/sqlite/include/sqlite3ext.h index 2e220798..7c1373fe 100644 --- a/mock/sqlite/include/sqlite3ext.h +++ b/mock/sqlite/include/sqlite3ext.h @@ -30,322 +30,322 @@ ** libraries! */ struct sqlite3_api_routines { - void * (*aggregate_context)(sqlite3_context*,int nBytes); - int (*aggregate_count)(sqlite3_context*); - int (*bind_blob)(sqlite3_stmt*,int,const void*,int n,void(*)(void*)); - int (*bind_double)(sqlite3_stmt*,int,double); - int (*bind_int)(sqlite3_stmt*,int,int); - int (*bind_int64)(sqlite3_stmt*,int,sqlite_int64); - int (*bind_null)(sqlite3_stmt*,int); - int (*bind_parameter_count)(sqlite3_stmt*); - int (*bind_parameter_index)(sqlite3_stmt*,const char*zName); - const char * (*bind_parameter_name)(sqlite3_stmt*,int); - int (*bind_text)(sqlite3_stmt*,int,const char*,int n,void(*)(void*)); - int (*bind_text16)(sqlite3_stmt*,int,const void*,int,void(*)(void*)); - int (*bind_value)(sqlite3_stmt*,int,const sqlite3_value*); - int (*busy_handler)(sqlite3*,int(*)(void*,int),void*); - int (*busy_timeout)(sqlite3*,int ms); - int (*changes)(sqlite3*); - int (*close)(sqlite3*); - int (*collation_needed)(sqlite3*,void*,void(*)(void*,sqlite3*, - int eTextRep,const char*)); - int (*collation_needed16)(sqlite3*,void*,void(*)(void*,sqlite3*, - int eTextRep,const void*)); - const void * (*column_blob)(sqlite3_stmt*,int iCol); - int (*column_bytes)(sqlite3_stmt*,int iCol); - int (*column_bytes16)(sqlite3_stmt*,int iCol); - int (*column_count)(sqlite3_stmt*pStmt); - const char * (*column_database_name)(sqlite3_stmt*,int); - const void * (*column_database_name16)(sqlite3_stmt*,int); - const char * (*column_decltype)(sqlite3_stmt*,int i); - const void * (*column_decltype16)(sqlite3_stmt*,int); - double (*column_double)(sqlite3_stmt*,int iCol); - int (*column_int)(sqlite3_stmt*,int iCol); - sqlite_int64 (*column_int64)(sqlite3_stmt*,int iCol); - const char * (*column_name)(sqlite3_stmt*,int); - const void * (*column_name16)(sqlite3_stmt*,int); - const char * (*column_origin_name)(sqlite3_stmt*,int); - const void * (*column_origin_name16)(sqlite3_stmt*,int); - const char * (*column_table_name)(sqlite3_stmt*,int); - const void * (*column_table_name16)(sqlite3_stmt*,int); - const unsigned char * (*column_text)(sqlite3_stmt*,int iCol); - const void * (*column_text16)(sqlite3_stmt*,int iCol); - int (*column_type)(sqlite3_stmt*,int iCol); - sqlite3_value* (*column_value)(sqlite3_stmt*,int iCol); - void * (*commit_hook)(sqlite3*,int(*)(void*),void*); - int (*complete)(const char*sql); - int (*complete16)(const void*sql); - int (*create_collation)(sqlite3*,const char*,int,void*, - int(*)(void*,int,const void*,int,const void*)); - int (*create_collation16)(sqlite3*,const void*,int,void*, - int(*)(void*,int,const void*,int,const void*)); - int (*create_function)(sqlite3*,const char*,int,int,void*, - void (*xFunc)(sqlite3_context*,int,sqlite3_value**), - void (*xStep)(sqlite3_context*,int,sqlite3_value**), - void (*xFinal)(sqlite3_context*)); - int (*create_function16)(sqlite3*,const void*,int,int,void*, - void (*xFunc)(sqlite3_context*,int,sqlite3_value**), - void (*xStep)(sqlite3_context*,int,sqlite3_value**), - void (*xFinal)(sqlite3_context*)); - int (*create_module)(sqlite3*,const char*,const sqlite3_module*,void*); - int (*data_count)(sqlite3_stmt*pStmt); - sqlite3 * (*db_handle)(sqlite3_stmt*); - int (*declare_vtab)(sqlite3*,const char*); - int (*enable_shared_cache)(int); - int (*errcode)(sqlite3*db); - const char * (*errmsg)(sqlite3*); - const void * (*errmsg16)(sqlite3*); - int (*exec)(sqlite3*,const char*,sqlite3_callback,void*,char**); - int (*expired)(sqlite3_stmt*); - int (*finalize)(sqlite3_stmt*pStmt); - void (*free)(void*); - void (*free_table)(char**result); - int (*get_autocommit)(sqlite3*); - void * (*get_auxdata)(sqlite3_context*,int); - int (*get_table)(sqlite3*,const char*,char***,int*,int*,char**); - int (*global_recover)(void); - void (*interruptx)(sqlite3*); - sqlite_int64 (*last_insert_rowid)(sqlite3*); - const char * (*libversion)(void); - int (*libversion_number)(void); - void *(*malloc)(int); - char * (*mprintf)(const char*,...); - int (*open)(const char*,sqlite3**); - int (*open16)(const void*,sqlite3**); - int (*prepare)(sqlite3*,const char*,int,sqlite3_stmt**,const char**); - int (*prepare16)(sqlite3*,const void*,int,sqlite3_stmt**,const void**); - void * (*profile)(sqlite3*,void(*)(void*,const char*,sqlite_uint64),void*); - void (*progress_handler)(sqlite3*,int,int(*)(void*),void*); - void *(*realloc)(void*,int); - int (*reset)(sqlite3_stmt*pStmt); - void (*result_blob)(sqlite3_context*,const void*,int,void(*)(void*)); - void (*result_double)(sqlite3_context*,double); - void (*result_error)(sqlite3_context*,const char*,int); - void (*result_error16)(sqlite3_context*,const void*,int); - void (*result_int)(sqlite3_context*,int); - void (*result_int64)(sqlite3_context*,sqlite_int64); - void (*result_null)(sqlite3_context*); - void (*result_text)(sqlite3_context*,const char*,int,void(*)(void*)); - void (*result_text16)(sqlite3_context*,const void*,int,void(*)(void*)); - void (*result_text16be)(sqlite3_context*,const void*,int,void(*)(void*)); - void (*result_text16le)(sqlite3_context*,const void*,int,void(*)(void*)); - void (*result_value)(sqlite3_context*,sqlite3_value*); - void * (*rollback_hook)(sqlite3*,void(*)(void*),void*); - int (*set_authorizer)(sqlite3*,int(*)(void*,int,const char*,const char*, - const char*,const char*),void*); - void (*set_auxdata)(sqlite3_context*,int,void*,void (*)(void*)); - char * (*xsnprintf)(int,char*,const char*,...); - int (*step)(sqlite3_stmt*); - int (*table_column_metadata)(sqlite3*,const char*,const char*,const char*, - char const**,char const**,int*,int*,int*); - void (*thread_cleanup)(void); - int (*total_changes)(sqlite3*); - void * (*trace)(sqlite3*,void(*xTrace)(void*,const char*),void*); - int (*transfer_bindings)(sqlite3_stmt*,sqlite3_stmt*); - void * (*update_hook)(sqlite3*,void(*)(void*,int ,char const*,char const*, - sqlite_int64),void*); - void * (*user_data)(sqlite3_context*); - const void * (*value_blob)(sqlite3_value*); - int (*value_bytes)(sqlite3_value*); - int (*value_bytes16)(sqlite3_value*); - double (*value_double)(sqlite3_value*); - int (*value_int)(sqlite3_value*); - sqlite_int64 (*value_int64)(sqlite3_value*); - int (*value_numeric_type)(sqlite3_value*); - const unsigned char * (*value_text)(sqlite3_value*); - const void * (*value_text16)(sqlite3_value*); - const void * (*value_text16be)(sqlite3_value*); - const void * (*value_text16le)(sqlite3_value*); - int (*value_type)(sqlite3_value*); - char *(*vmprintf)(const char*,va_list); - /* Added ??? */ - int (*overload_function)(sqlite3*, const char *zFuncName, int nArg); - /* Added by 3.3.13 */ - int (*prepare_v2)(sqlite3*,const char*,int,sqlite3_stmt**,const char**); - int (*prepare16_v2)(sqlite3*,const void*,int,sqlite3_stmt**,const void**); - int (*clear_bindings)(sqlite3_stmt*); - /* Added by 3.4.1 */ - int (*create_module_v2)(sqlite3*,const char*,const sqlite3_module*,void*, - void (*xDestroy)(void *)); - /* Added by 3.5.0 */ - int (*bind_zeroblob)(sqlite3_stmt*,int,int); - int (*blob_bytes)(sqlite3_blob*); - int (*blob_close)(sqlite3_blob*); - int (*blob_open)(sqlite3*,const char*,const char*,const char*,sqlite3_int64, - int,sqlite3_blob**); - int (*blob_read)(sqlite3_blob*,void*,int,int); - int (*blob_write)(sqlite3_blob*,const void*,int,int); - int (*create_collation_v2)(sqlite3*,const char*,int,void*, - int(*)(void*,int,const void*,int,const void*), - void(*)(void*)); - int (*file_control)(sqlite3*,const char*,int,void*); - sqlite3_int64 (*memory_highwater)(int); - sqlite3_int64 (*memory_used)(void); - sqlite3_mutex *(*mutex_alloc)(int); - void (*mutex_enter)(sqlite3_mutex*); - void (*mutex_free)(sqlite3_mutex*); - void (*mutex_leave)(sqlite3_mutex*); - int (*mutex_try)(sqlite3_mutex*); - int (*open_v2)(const char*,sqlite3**,int,const char*); - int (*release_memory)(int); - void (*result_error_nomem)(sqlite3_context*); - void (*result_error_toobig)(sqlite3_context*); - int (*sleep)(int); - void (*soft_heap_limit)(int); - sqlite3_vfs *(*vfs_find)(const char*); - int (*vfs_register)(sqlite3_vfs*,int); - int (*vfs_unregister)(sqlite3_vfs*); - int (*xthreadsafe)(void); - void (*result_zeroblob)(sqlite3_context*,int); - void (*result_error_code)(sqlite3_context*,int); - int (*test_control)(int, ...); - void (*randomness)(int,void*); - sqlite3 *(*context_db_handle)(sqlite3_context*); - int (*extended_result_codes)(sqlite3*,int); - int (*limit)(sqlite3*,int,int); - sqlite3_stmt *(*next_stmt)(sqlite3*,sqlite3_stmt*); - const char *(*sql)(sqlite3_stmt*); - int (*status)(int,int*,int*,int); - int (*backup_finish)(sqlite3_backup*); - sqlite3_backup *(*backup_init)(sqlite3*,const char*,sqlite3*,const char*); - int (*backup_pagecount)(sqlite3_backup*); - int (*backup_remaining)(sqlite3_backup*); - int (*backup_step)(sqlite3_backup*,int); - const char *(*compileoption_get)(int); - int (*compileoption_used)(const char*); - int (*create_function_v2)(sqlite3*,const char*,int,int,void*, - void (*xFunc)(sqlite3_context*,int,sqlite3_value**), - void (*xStep)(sqlite3_context*,int,sqlite3_value**), - void (*xFinal)(sqlite3_context*), - void(*xDestroy)(void*)); - int (*db_config)(sqlite3*,int,...); - sqlite3_mutex *(*db_mutex)(sqlite3*); - int (*db_status)(sqlite3*,int,int*,int*,int); - int (*extended_errcode)(sqlite3*); - void (*log)(int,const char*,...); - sqlite3_int64 (*soft_heap_limit64)(sqlite3_int64); - const char *(*sourceid)(void); - int (*stmt_status)(sqlite3_stmt*,int,int); - int (*strnicmp)(const char*,const char*,int); - int (*unlock_notify)(sqlite3*,void(*)(void**,int),void*); - int (*wal_autocheckpoint)(sqlite3*,int); - int (*wal_checkpoint)(sqlite3*,const char*); - void *(*wal_hook)(sqlite3*,int(*)(void*,sqlite3*,const char*,int),void*); - int (*blob_reopen)(sqlite3_blob*,sqlite3_int64); - int (*vtab_config)(sqlite3*,int op,...); - int (*vtab_on_conflict)(sqlite3*); - /* Version 3.7.16 and later */ - int (*close_v2)(sqlite3*); - const char *(*db_filename)(sqlite3*,const char*); - int (*db_readonly)(sqlite3*,const char*); - int (*db_release_memory)(sqlite3*); - const char *(*errstr)(int); - int (*stmt_busy)(sqlite3_stmt*); - int (*stmt_readonly)(sqlite3_stmt*); - int (*stricmp)(const char*,const char*); - int (*uri_boolean)(const char*,const char*,int); - sqlite3_int64 (*uri_int64)(const char*,const char*,sqlite3_int64); - const char *(*uri_parameter)(const char*,const char*); - char *(*xvsnprintf)(int,char*,const char*,va_list); - int (*wal_checkpoint_v2)(sqlite3*,const char*,int,int*,int*); - /* Version 3.8.7 and later */ - int (*auto_extension)(void(*)(void)); - int (*bind_blob64)(sqlite3_stmt*,int,const void*,sqlite3_uint64, - void(*)(void*)); - int (*bind_text64)(sqlite3_stmt*,int,const char*,sqlite3_uint64, - void(*)(void*),unsigned char); - int (*cancel_auto_extension)(void(*)(void)); - int (*load_extension)(sqlite3*,const char*,const char*,char**); - void *(*malloc64)(sqlite3_uint64); - sqlite3_uint64 (*msize)(void*); - void *(*realloc64)(void*,sqlite3_uint64); - void (*reset_auto_extension)(void); - void (*result_blob64)(sqlite3_context*,const void*,sqlite3_uint64, - void(*)(void*)); - void (*result_text64)(sqlite3_context*,const char*,sqlite3_uint64, - void(*)(void*), unsigned char); - int (*strglob)(const char*,const char*); - /* Version 3.8.11 and later */ - sqlite3_value *(*value_dup)(const sqlite3_value*); - void (*value_free)(sqlite3_value*); - int (*result_zeroblob64)(sqlite3_context*,sqlite3_uint64); - int (*bind_zeroblob64)(sqlite3_stmt*, int, sqlite3_uint64); - /* Version 3.9.0 and later */ - unsigned int (*value_subtype)(sqlite3_value*); - void (*result_subtype)(sqlite3_context*,unsigned int); - /* Version 3.10.0 and later */ - int (*status64)(int,sqlite3_int64*,sqlite3_int64*,int); - int (*strlike)(const char*,const char*,unsigned int); - int (*db_cacheflush)(sqlite3*); - /* Version 3.12.0 and later */ - int (*system_errno)(sqlite3*); - /* Version 3.14.0 and later */ - int (*trace_v2)(sqlite3*,unsigned,int(*)(unsigned,void*,void*,void*),void*); - char *(*expanded_sql)(sqlite3_stmt*); - /* Version 3.18.0 and later */ - void (*set_last_insert_rowid)(sqlite3*,sqlite3_int64); - /* Version 3.20.0 and later */ - int (*prepare_v3)(sqlite3*,const char*,int,unsigned int, - sqlite3_stmt**,const char**); - int (*prepare16_v3)(sqlite3*,const void*,int,unsigned int, - sqlite3_stmt**,const void**); - int (*bind_pointer)(sqlite3_stmt*,int,void*,const char*,void(*)(void*)); - void (*result_pointer)(sqlite3_context*,void*,const char*,void(*)(void*)); - void *(*value_pointer)(sqlite3_value*,const char*); - int (*vtab_nochange)(sqlite3_context*); - int (*value_nochange)(sqlite3_value*); - const char *(*vtab_collation)(sqlite3_index_info*,int); - /* Version 3.24.0 and later */ - int (*keyword_count)(void); - int (*keyword_name)(int,const char**,int*); - int (*keyword_check)(const char*,int); - sqlite3_str *(*str_new)(sqlite3*); - char *(*str_finish)(sqlite3_str*); - void (*str_appendf)(sqlite3_str*, const char *zFormat, ...); - void (*str_vappendf)(sqlite3_str*, const char *zFormat, va_list); - void (*str_append)(sqlite3_str*, const char *zIn, int N); - void (*str_appendall)(sqlite3_str*, const char *zIn); - void (*str_appendchar)(sqlite3_str*, int N, char C); - void (*str_reset)(sqlite3_str*); - int (*str_errcode)(sqlite3_str*); - int (*str_length)(sqlite3_str*); - char *(*str_value)(sqlite3_str*); - /* Version 3.25.0 and later */ - int (*create_window_function)(sqlite3*,const char*,int,int,void*, - void (*xStep)(sqlite3_context*,int,sqlite3_value**), - void (*xFinal)(sqlite3_context*), - void (*xValue)(sqlite3_context*), - void (*xInv)(sqlite3_context*,int,sqlite3_value**), - void(*xDestroy)(void*)); - /* Version 3.26.0 and later */ - const char *(*normalized_sql)(sqlite3_stmt*); - /* Version 3.28.0 and later */ - int (*stmt_isexplain)(sqlite3_stmt*); - int (*value_frombind)(sqlite3_value*); - /* Version 3.30.0 and later */ - int (*drop_modules)(sqlite3*,const char**); - /* Version 3.31.0 and later */ - sqlite3_int64 (*hard_heap_limit64)(sqlite3_int64); - const char *(*uri_key)(const char*,int); - const char *(*filename_database)(const char*); - const char *(*filename_journal)(const char*); - const char *(*filename_wal)(const char*); - /* Version 3.32.0 and later */ - char *(*create_filename)(const char*,const char*,const char*, - int,const char**); - void (*free_filename)(char*); - sqlite3_file *(*database_file_object)(const char*); - /* Version 3.34.0 and later */ - int (*txn_state)(sqlite3*,const char*); - /* Version 3.36.1 and later */ - sqlite3_int64 (*changes64)(sqlite3*); - sqlite3_int64 (*total_changes64)(sqlite3*); - /* Version 3.37.0 and later */ - int (*autovacuum_pages)(sqlite3*, - unsigned int(*)(void*,const char*,unsigned int,unsigned int,unsigned int), - void*, void(*)(void*)); + void * (*aggregate_context)(sqlite3_context*,int nBytes); + int (*aggregate_count)(sqlite3_context*); + int (*bind_blob)(sqlite3_stmt*,int,const void*,int n,void(*)(void*)); + int (*bind_double)(sqlite3_stmt*,int,double); + int (*bind_int)(sqlite3_stmt*,int,int); + int (*bind_int64)(sqlite3_stmt*,int,sqlite_int64); + int (*bind_null)(sqlite3_stmt*,int); + int (*bind_parameter_count)(sqlite3_stmt*); + int (*bind_parameter_index)(sqlite3_stmt*,const char*zName); + const char * (*bind_parameter_name)(sqlite3_stmt*,int); + int (*bind_text)(sqlite3_stmt*,int,const char*,int n,void(*)(void*)); + int (*bind_text16)(sqlite3_stmt*,int,const void*,int,void(*)(void*)); + int (*bind_value)(sqlite3_stmt*,int,const sqlite3_value*); + int (*busy_handler)(sqlite3*,int(*)(void*,int),void*); + int (*busy_timeout)(sqlite3*,int ms); + int (*changes)(sqlite3*); + int (*close)(sqlite3*); + int (*collation_needed)(sqlite3*,void*,void(*)(void*,sqlite3*, + int eTextRep,const char*)); + int (*collation_needed16)(sqlite3*,void*,void(*)(void*,sqlite3*, + int eTextRep,const void*)); + const void * (*column_blob)(sqlite3_stmt*,int iCol); + int (*column_bytes)(sqlite3_stmt*,int iCol); + int (*column_bytes16)(sqlite3_stmt*,int iCol); + int (*column_count)(sqlite3_stmt*pStmt); + const char * (*column_database_name)(sqlite3_stmt*,int); + const void * (*column_database_name16)(sqlite3_stmt*,int); + const char * (*column_decltype)(sqlite3_stmt*,int i); + const void * (*column_decltype16)(sqlite3_stmt*,int); + double (*column_double)(sqlite3_stmt*,int iCol); + int (*column_int)(sqlite3_stmt*,int iCol); + sqlite_int64 (*column_int64)(sqlite3_stmt*,int iCol); + const char * (*column_name)(sqlite3_stmt*,int); + const void * (*column_name16)(sqlite3_stmt*,int); + const char * (*column_origin_name)(sqlite3_stmt*,int); + const void * (*column_origin_name16)(sqlite3_stmt*,int); + const char * (*column_table_name)(sqlite3_stmt*,int); + const void * (*column_table_name16)(sqlite3_stmt*,int); + const unsigned char * (*column_text)(sqlite3_stmt*,int iCol); + const void * (*column_text16)(sqlite3_stmt*,int iCol); + int (*column_type)(sqlite3_stmt*,int iCol); + sqlite3_value* (*column_value)(sqlite3_stmt*,int iCol); + void * (*commit_hook)(sqlite3*,int(*)(void*),void*); + int (*complete)(const char*sql); + int (*complete16)(const void*sql); + int (*create_collation)(sqlite3*,const char*,int,void*, + int(*)(void*,int,const void*,int,const void*)); + int (*create_collation16)(sqlite3*,const void*,int,void*, + int(*)(void*,int,const void*,int,const void*)); + int (*create_function)(sqlite3*,const char*,int,int,void*, + void (*xFunc)(sqlite3_context*,int,sqlite3_value**), + void (*xStep)(sqlite3_context*,int,sqlite3_value**), + void (*xFinal)(sqlite3_context*)); + int (*create_function16)(sqlite3*,const void*,int,int,void*, + void (*xFunc)(sqlite3_context*,int,sqlite3_value**), + void (*xStep)(sqlite3_context*,int,sqlite3_value**), + void (*xFinal)(sqlite3_context*)); + int (*create_module)(sqlite3*,const char*,const sqlite3_module*,void*); + int (*data_count)(sqlite3_stmt*pStmt); + sqlite3 * (*db_handle)(sqlite3_stmt*); + int (*declare_vtab)(sqlite3*,const char*); + int (*enable_shared_cache)(int); + int (*errcode)(sqlite3*db); + const char * (*errmsg)(sqlite3*); + const void * (*errmsg16)(sqlite3*); + int (*exec)(sqlite3*,const char*,sqlite3_callback,void*,char**); + int (*expired)(sqlite3_stmt*); + int (*finalize)(sqlite3_stmt*pStmt); + void (*free)(void*); + void (*free_table)(char**result); + int (*get_autocommit)(sqlite3*); + void * (*get_auxdata)(sqlite3_context*,int); + int (*get_table)(sqlite3*,const char*,char***,int*,int*,char**); + int (*global_recover)(void); + void (*interruptx)(sqlite3*); + sqlite_int64 (*last_insert_rowid)(sqlite3*); + const char * (*libversion)(void); + int (*libversion_number)(void); + void *(*malloc)(int); + char * (*mprintf)(const char*,...); + int (*open)(const char*,sqlite3**); + int (*open16)(const void*,sqlite3**); + int (*prepare)(sqlite3*,const char*,int,sqlite3_stmt**,const char**); + int (*prepare16)(sqlite3*,const void*,int,sqlite3_stmt**,const void**); + void * (*profile)(sqlite3*,void(*)(void*,const char*,sqlite_uint64),void*); + void (*progress_handler)(sqlite3*,int,int(*)(void*),void*); + void *(*realloc)(void*,int); + int (*reset)(sqlite3_stmt*pStmt); + void (*result_blob)(sqlite3_context*,const void*,int,void(*)(void*)); + void (*result_double)(sqlite3_context*,double); + void (*result_error)(sqlite3_context*,const char*,int); + void (*result_error16)(sqlite3_context*,const void*,int); + void (*result_int)(sqlite3_context*,int); + void (*result_int64)(sqlite3_context*,sqlite_int64); + void (*result_null)(sqlite3_context*); + void (*result_text)(sqlite3_context*,const char*,int,void(*)(void*)); + void (*result_text16)(sqlite3_context*,const void*,int,void(*)(void*)); + void (*result_text16be)(sqlite3_context*,const void*,int,void(*)(void*)); + void (*result_text16le)(sqlite3_context*,const void*,int,void(*)(void*)); + void (*result_value)(sqlite3_context*,sqlite3_value*); + void * (*rollback_hook)(sqlite3*,void(*)(void*),void*); + int (*set_authorizer)(sqlite3*,int(*)(void*,int,const char*,const char*, + const char*,const char*),void*); + void (*set_auxdata)(sqlite3_context*,int,void*,void (*)(void*)); + char * (*xsnprintf)(int,char*,const char*,...); + int (*step)(sqlite3_stmt*); + int (*table_column_metadata)(sqlite3*,const char*,const char*,const char*, + char const**,char const**,int*,int*,int*); + void (*thread_cleanup)(void); + int (*total_changes)(sqlite3*); + void * (*trace)(sqlite3*,void(*xTrace)(void*,const char*),void*); + int (*transfer_bindings)(sqlite3_stmt*,sqlite3_stmt*); + void * (*update_hook)(sqlite3*,void(*)(void*,int ,char const*,char const*, + sqlite_int64),void*); + void * (*user_data)(sqlite3_context*); + const void * (*value_blob)(sqlite3_value*); + int (*value_bytes)(sqlite3_value*); + int (*value_bytes16)(sqlite3_value*); + double (*value_double)(sqlite3_value*); + int (*value_int)(sqlite3_value*); + sqlite_int64 (*value_int64)(sqlite3_value*); + int (*value_numeric_type)(sqlite3_value*); + const unsigned char * (*value_text)(sqlite3_value*); + const void * (*value_text16)(sqlite3_value*); + const void * (*value_text16be)(sqlite3_value*); + const void * (*value_text16le)(sqlite3_value*); + int (*value_type)(sqlite3_value*); + char *(*vmprintf)(const char*,va_list); + /* Added ??? */ + int (*overload_function)(sqlite3*, const char *zFuncName, int nArg); + /* Added by 3.3.13 */ + int (*prepare_v2)(sqlite3*,const char*,int,sqlite3_stmt**,const char**); + int (*prepare16_v2)(sqlite3*,const void*,int,sqlite3_stmt**,const void**); + int (*clear_bindings)(sqlite3_stmt*); + /* Added by 3.4.1 */ + int (*create_module_v2)(sqlite3*,const char*,const sqlite3_module*,void*, + void (*xDestroy)(void *)); + /* Added by 3.5.0 */ + int (*bind_zeroblob)(sqlite3_stmt*,int,int); + int (*blob_bytes)(sqlite3_blob*); + int (*blob_close)(sqlite3_blob*); + int (*blob_open)(sqlite3*,const char*,const char*,const char*,sqlite3_int64, + int,sqlite3_blob**); + int (*blob_read)(sqlite3_blob*,void*,int,int); + int (*blob_write)(sqlite3_blob*,const void*,int,int); + int (*create_collation_v2)(sqlite3*,const char*,int,void*, + int(*)(void*,int,const void*,int,const void*), + void(*)(void*)); + int (*file_control)(sqlite3*,const char*,int,void*); + sqlite3_int64 (*memory_highwater)(int); + sqlite3_int64 (*memory_used)(void); + sqlite3_mutex *(*mutex_alloc)(int); + void (*mutex_enter)(sqlite3_mutex*); + void (*mutex_free)(sqlite3_mutex*); + void (*mutex_leave)(sqlite3_mutex*); + int (*mutex_try)(sqlite3_mutex*); + int (*open_v2)(const char*,sqlite3**,int,const char*); + int (*release_memory)(int); + void (*result_error_nomem)(sqlite3_context*); + void (*result_error_toobig)(sqlite3_context*); + int (*sleep)(int); + void (*soft_heap_limit)(int); + sqlite3_vfs *(*vfs_find)(const char*); + int (*vfs_register)(sqlite3_vfs*,int); + int (*vfs_unregister)(sqlite3_vfs*); + int (*xthreadsafe)(void); + void (*result_zeroblob)(sqlite3_context*,int); + void (*result_error_code)(sqlite3_context*,int); + int (*test_control)(int, ...); + void (*randomness)(int,void*); + sqlite3 *(*context_db_handle)(sqlite3_context*); + int (*extended_result_codes)(sqlite3*,int); + int (*limit)(sqlite3*,int,int); + sqlite3_stmt *(*next_stmt)(sqlite3*,sqlite3_stmt*); + const char *(*sql)(sqlite3_stmt*); + int (*status)(int,int*,int*,int); + int (*backup_finish)(sqlite3_backup*); + sqlite3_backup *(*backup_init)(sqlite3*,const char*,sqlite3*,const char*); + int (*backup_pagecount)(sqlite3_backup*); + int (*backup_remaining)(sqlite3_backup*); + int (*backup_step)(sqlite3_backup*,int); + const char *(*compileoption_get)(int); + int (*compileoption_used)(const char*); + int (*create_function_v2)(sqlite3*,const char*,int,int,void*, + void (*xFunc)(sqlite3_context*,int,sqlite3_value**), + void (*xStep)(sqlite3_context*,int,sqlite3_value**), + void (*xFinal)(sqlite3_context*), + void(*xDestroy)(void*)); + int (*db_config)(sqlite3*,int,...); + sqlite3_mutex *(*db_mutex)(sqlite3*); + int (*db_status)(sqlite3*,int,int*,int*,int); + int (*extended_errcode)(sqlite3*); + void (*log)(int,const char*,...); + sqlite3_int64 (*soft_heap_limit64)(sqlite3_int64); + const char *(*sourceid)(void); + int (*stmt_status)(sqlite3_stmt*,int,int); + int (*strnicmp)(const char*,const char*,int); + int (*unlock_notify)(sqlite3*,void(*)(void**,int),void*); + int (*wal_autocheckpoint)(sqlite3*,int); + int (*wal_checkpoint)(sqlite3*,const char*); + void *(*wal_hook)(sqlite3*,int(*)(void*,sqlite3*,const char*,int),void*); + int (*blob_reopen)(sqlite3_blob*,sqlite3_int64); + int (*vtab_config)(sqlite3*,int op,...); + int (*vtab_on_conflict)(sqlite3*); + /* Version 3.7.16 and later */ + int (*close_v2)(sqlite3*); + const char *(*db_filename)(sqlite3*,const char*); + int (*db_readonly)(sqlite3*,const char*); + int (*db_release_memory)(sqlite3*); + const char *(*errstr)(int); + int (*stmt_busy)(sqlite3_stmt*); + int (*stmt_readonly)(sqlite3_stmt*); + int (*stricmp)(const char*,const char*); + int (*uri_boolean)(const char*,const char*,int); + sqlite3_int64 (*uri_int64)(const char*,const char*,sqlite3_int64); + const char *(*uri_parameter)(const char*,const char*); + char *(*xvsnprintf)(int,char*,const char*,va_list); + int (*wal_checkpoint_v2)(sqlite3*,const char*,int,int*,int*); + /* Version 3.8.7 and later */ + int (*auto_extension)(void(*)(void)); + int (*bind_blob64)(sqlite3_stmt*,int,const void*,sqlite3_uint64, + void(*)(void*)); + int (*bind_text64)(sqlite3_stmt*,int,const char*,sqlite3_uint64, + void(*)(void*),unsigned char); + int (*cancel_auto_extension)(void(*)(void)); + int (*load_extension)(sqlite3*,const char*,const char*,char**); + void *(*malloc64)(sqlite3_uint64); + sqlite3_uint64 (*msize)(void*); + void *(*realloc64)(void*,sqlite3_uint64); + void (*reset_auto_extension)(void); + void (*result_blob64)(sqlite3_context*,const void*,sqlite3_uint64, + void(*)(void*)); + void (*result_text64)(sqlite3_context*,const char*,sqlite3_uint64, + void(*)(void*), unsigned char); + int (*strglob)(const char*,const char*); + /* Version 3.8.11 and later */ + sqlite3_value *(*value_dup)(const sqlite3_value*); + void (*value_free)(sqlite3_value*); + int (*result_zeroblob64)(sqlite3_context*,sqlite3_uint64); + int (*bind_zeroblob64)(sqlite3_stmt*, int, sqlite3_uint64); + /* Version 3.9.0 and later */ + unsigned int (*value_subtype)(sqlite3_value*); + void (*result_subtype)(sqlite3_context*,unsigned int); + /* Version 3.10.0 and later */ + int (*status64)(int,sqlite3_int64*,sqlite3_int64*,int); + int (*strlike)(const char*,const char*,unsigned int); + int (*db_cacheflush)(sqlite3*); + /* Version 3.12.0 and later */ + int (*system_errno)(sqlite3*); + /* Version 3.14.0 and later */ + int (*trace_v2)(sqlite3*,unsigned,int(*)(unsigned,void*,void*,void*),void*); + char *(*expanded_sql)(sqlite3_stmt*); + /* Version 3.18.0 and later */ + void (*set_last_insert_rowid)(sqlite3*,sqlite3_int64); + /* Version 3.20.0 and later */ + int (*prepare_v3)(sqlite3*,const char*,int,unsigned int, + sqlite3_stmt**,const char**); + int (*prepare16_v3)(sqlite3*,const void*,int,unsigned int, + sqlite3_stmt**,const void**); + int (*bind_pointer)(sqlite3_stmt*,int,void*,const char*,void(*)(void*)); + void (*result_pointer)(sqlite3_context*,void*,const char*,void(*)(void*)); + void *(*value_pointer)(sqlite3_value*,const char*); + int (*vtab_nochange)(sqlite3_context*); + int (*value_nochange)(sqlite3_value*); + const char *(*vtab_collation)(sqlite3_index_info*,int); + /* Version 3.24.0 and later */ + int (*keyword_count)(void); + int (*keyword_name)(int,const char**,int*); + int (*keyword_check)(const char*,int); + sqlite3_str *(*str_new)(sqlite3*); + char *(*str_finish)(sqlite3_str*); + void (*str_appendf)(sqlite3_str*, const char *zFormat, ...); + void (*str_vappendf)(sqlite3_str*, const char *zFormat, va_list); + void (*str_append)(sqlite3_str*, const char *zIn, int N); + void (*str_appendall)(sqlite3_str*, const char *zIn); + void (*str_appendchar)(sqlite3_str*, int N, char C); + void (*str_reset)(sqlite3_str*); + int (*str_errcode)(sqlite3_str*); + int (*str_length)(sqlite3_str*); + char *(*str_value)(sqlite3_str*); + /* Version 3.25.0 and later */ + int (*create_window_function)(sqlite3*,const char*,int,int,void*, + void (*xStep)(sqlite3_context*,int,sqlite3_value**), + void (*xFinal)(sqlite3_context*), + void (*xValue)(sqlite3_context*), + void (*xInv)(sqlite3_context*,int,sqlite3_value**), + void(*xDestroy)(void*)); + /* Version 3.26.0 and later */ + const char *(*normalized_sql)(sqlite3_stmt*); + /* Version 3.28.0 and later */ + int (*stmt_isexplain)(sqlite3_stmt*); + int (*value_frombind)(sqlite3_value*); + /* Version 3.30.0 and later */ + int (*drop_modules)(sqlite3*,const char**); + /* Version 3.31.0 and later */ + sqlite3_int64 (*hard_heap_limit64)(sqlite3_int64); + const char *(*uri_key)(const char*,int); + const char *(*filename_database)(const char*); + const char *(*filename_journal)(const char*); + const char *(*filename_wal)(const char*); + /* Version 3.32.0 and later */ + char *(*create_filename)(const char*,const char*,const char*, + int,const char**); + void (*free_filename)(char*); + sqlite3_file *(*database_file_object)(const char*); + /* Version 3.34.0 and later */ + int (*txn_state)(sqlite3*,const char*); + /* Version 3.36.1 and later */ + sqlite3_int64 (*changes64)(sqlite3*); + sqlite3_int64 (*total_changes64)(sqlite3*); + /* Version 3.37.0 and later */ + int (*autovacuum_pages)(sqlite3*, + unsigned int(*)(void*,const char*,unsigned int,unsigned int,unsigned int), + void*, void(*)(void*)); #ifdef SQLITE_ENABLE_DROPTABLE_CALLBACK - int (*set_droptable_handle)(sqlite3*,void(*)(sqlite3*,const char*,const char*)); + int (*set_droptable_handle)(sqlite3*,void(*)(sqlite3*,const char*,const char*)); #endif }; @@ -354,9 +354,9 @@ struct sqlite3_api_routines { ** is also defined in the file "loadext.c". */ typedef int (*sqlite3_loadext_entry)( - sqlite3 *db, /* Handle to the database. */ - char **pzErrMsg, /* Used to set error string on failure. */ - const sqlite3_api_routines *pThunk /* Extension API function pointers. */ + sqlite3 *db, /* Handle to the database. */ + char **pzErrMsg, /* Used to set error string on failure. */ + const sqlite3_api_routines *pThunk /* Extension API function pointers. */ ); /* @@ -669,14 +669,14 @@ extern const sqlite3_api_routines *sqlite3_export_symbols; #endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */ #if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) -/* This case when the file really is being compiled as a loadable + /* This case when the file really is being compiled as a loadable ** extension */ # define SQLITE_EXTENSION_INIT1 const sqlite3_api_routines *sqlite3_api=0; # define SQLITE_EXTENSION_INIT2(v) sqlite3_api=v; # define SQLITE_EXTENSION_INIT3 \ extern const sqlite3_api_routines *sqlite3_api; #else -/* This case when the file is being statically linked into the + /* This case when the file is being statically linked into the ** application */ # define SQLITE_EXTENSION_INIT1 /*no-op*/ # define SQLITE_EXTENSION_INIT2(v) (void)v; /* unused parameter */ diff --git a/mock/sqlite/include/sqlite3sym.h b/mock/sqlite/include/sqlite3sym.h index 56eeef3a..bd459b3e 100644 --- a/mock/sqlite/include/sqlite3sym.h +++ b/mock/sqlite/include/sqlite3sym.h @@ -1,17 +1,17 @@ /* -* 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. -*/ + * 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 SQLITE3SYM_H #define SQLITE3SYM_H @@ -23,12 +23,12 @@ #include "sqlite3ext.h" struct sqlite3_api_routines_hw { - int (*initialize)(); - int (*config)(int,...); - int (*key)(sqlite3*,const void*,int); - int (*key_v2)(sqlite3*,const char*,const void*,int); - int (*rekey)(sqlite3*,const void*,int); - int (*rekey_v2)(sqlite3*,const char*,const void*,int); + int (*initialize)(); + int (*config)(int,...); + int (*key)(sqlite3*,const void*,int); + int (*key_v2)(sqlite3*,const char*,const void*,int); + int (*rekey)(sqlite3*,const void*,int); + int (*rekey_v2)(sqlite3*,const char*,const void*,int); }; extern const struct sqlite3_api_routines_hw *sqlite3_export_hw_symbols; diff --git a/mock/sqlite/src/shell.c b/mock/sqlite/src/shell.c index b772572f..dc66c400 100644 --- a/mock/sqlite/src/shell.c +++ b/mock/sqlite/src/shell.c @@ -37,7 +37,7 @@ /* ** Optionally #include a user-defined header, whereby compilation options -** may be set prior to where they take effect, but after platform setup. +** may be set prior to where they take effect, but after platform setup. ** If SQLITE_CUSTOM_INCLUDE=? is defined, its value names the #include ** file. Note that this macro has a like effect on sqlite3.c compilation. */ @@ -188,14 +188,14 @@ typedef unsigned char u8; # define pclose _pclose # endif #else -/* Make sure isatty() has a prototype. */ -extern int isatty(int); + /* Make sure isatty() has a prototype. */ + extern int isatty(int); # if !defined(__RTP__) && !defined(_WRS_KERNEL) -/* popen and pclose are not C89 functions and so are + /* popen and pclose are not C89 functions and so are ** sometimes omitted from the header */ -extern FILE *popen(const char*,const char*); -extern int pclose(FILE*); + extern FILE *popen(const char*,const char*); + extern int pclose(FILE*); # else # define SQLITE_OMIT_POPEN 1 # endif @@ -235,12 +235,12 @@ extern LPWSTR sqlite3_win32_utf8_to_unicode(const char *zText); */ #if (defined(_WIN32) || defined(WIN32)) && !SQLITE_OS_WINRT static void setBinaryMode(FILE *file, int isOutput){ - if( isOutput ) fflush(file); - _setmode(_fileno(file), _O_BINARY); + if( isOutput ) fflush(file); + _setmode(_fileno(file), _O_BINARY); } static void setTextMode(FILE *file, int isOutput){ - if( isOutput ) fflush(file); - _setmode(_fileno(file), _O_TEXT); + if( isOutput ) fflush(file); + _setmode(_fileno(file), _O_TEXT); } #else # define setBinaryMode(X,Y) @@ -253,18 +253,18 @@ static int enableTimer = 0; /* Return the current wall-clock time */ static sqlite3_int64 timeOfDay(void){ - static sqlite3_vfs *clockVfs = 0; - sqlite3_int64 t; - if( clockVfs==0 ) clockVfs = sqlite3_vfs_find(0); - if( clockVfs==0 ) return 0; /* Never actually happens */ - if( clockVfs->iVersion>=2 && clockVfs->xCurrentTimeInt64!=0 ){ - clockVfs->xCurrentTimeInt64(clockVfs, &t); - }else{ - double r; - clockVfs->xCurrentTime(clockVfs, &r); - t = (sqlite3_int64)(r*86400000.0); - } - return t; + static sqlite3_vfs *clockVfs = 0; + sqlite3_int64 t; + if( clockVfs==0 ) clockVfs = sqlite3_vfs_find(0); + if( clockVfs==0 ) return 0; /* Never actually happens */ + if( clockVfs->iVersion>=2 && clockVfs->xCurrentTimeInt64!=0 ){ + clockVfs->xCurrentTimeInt64(clockVfs, &t); + }else{ + double r; + clockVfs->xCurrentTime(clockVfs, &r); + t = (sqlite3_int64)(r*86400000.0); + } + return t; } #if !defined(_WIN32) && !defined(WIN32) && !defined(__minux) @@ -274,8 +274,8 @@ static sqlite3_int64 timeOfDay(void){ /* VxWorks does not support getrusage() as far as we can determine */ #if defined(_WRS_KERNEL) || defined(__RTP__) struct rusage { - struct timeval ru_utime; /* user CPU time used */ - struct timeval ru_stime; /* system CPU time used */ + struct timeval ru_utime; /* user CPU time used */ + struct timeval ru_stime; /* system CPU time used */ }; #define getrusage(A,B) memset(B,0,sizeof(*B)) #endif @@ -288,31 +288,31 @@ static sqlite3_int64 iBegin; /* Wall-clock time at start */ ** Begin timing an operation */ static void beginTimer(void){ - if( enableTimer ){ - getrusage(RUSAGE_SELF, &sBegin); - iBegin = timeOfDay(); - } + if( enableTimer ){ + getrusage(RUSAGE_SELF, &sBegin); + iBegin = timeOfDay(); + } } /* Return the difference of two time_structs in seconds */ static double timeDiff(struct timeval *pStart, struct timeval *pEnd){ - return (pEnd->tv_usec - pStart->tv_usec)*0.000001 + - (double)(pEnd->tv_sec - pStart->tv_sec); + return (pEnd->tv_usec - pStart->tv_usec)*0.000001 + + (double)(pEnd->tv_sec - pStart->tv_sec); } /* ** Print the timing results. */ static void endTimer(void){ - if( enableTimer ){ - sqlite3_int64 iEnd = timeOfDay(); - struct rusage sEnd; - getrusage(RUSAGE_SELF, &sEnd); - printf("Run Time: real %.3f user %f sys %f\n", - (iEnd - iBegin)*0.001, - timeDiff(&sBegin.ru_utime, &sEnd.ru_utime), - timeDiff(&sBegin.ru_stime, &sEnd.ru_stime)); - } + if( enableTimer ){ + sqlite3_int64 iEnd = timeOfDay(); + struct rusage sEnd; + getrusage(RUSAGE_SELF, &sEnd); + printf("Run Time: real %.3f user %f sys %f\n", + (iEnd - iBegin)*0.001, + timeDiff(&sBegin.ru_utime, &sEnd.ru_utime), + timeDiff(&sBegin.ru_stime, &sEnd.ru_stime)); + } } #define BEGIN_TIMER beginTimer() @@ -327,7 +327,7 @@ static FILETIME ftKernelBegin; static FILETIME ftUserBegin; static sqlite3_int64 ftWallBegin; typedef BOOL (WINAPI *GETPROCTIMES)(HANDLE, LPFILETIME, LPFILETIME, - LPFILETIME, LPFILETIME); + LPFILETIME, LPFILETIME); static GETPROCTIMES getProcessTimesAddr = NULL; /* @@ -335,63 +335,63 @@ static GETPROCTIMES getProcessTimesAddr = NULL; ** support found (or found previously). */ static int hasTimer(void){ - if( getProcessTimesAddr ){ - return 1; - } else { + if( getProcessTimesAddr ){ + return 1; + } else { #if !SQLITE_OS_WINRT - /* GetProcessTimes() isn't supported in WIN95 and some other Windows + /* GetProcessTimes() isn't supported in WIN95 and some other Windows ** versions. See if the version we are running on has it, and if it ** does, save off a pointer to it and the current process handle. */ - hProcess = GetCurrentProcess(); - if( hProcess ){ - HINSTANCE hinstLib = LoadLibrary(TEXT("Kernel32.dll")); - if( NULL != hinstLib ){ - getProcessTimesAddr = - (GETPROCTIMES) GetProcAddress(hinstLib, "GetProcessTimes"); - if( NULL != getProcessTimesAddr ){ - return 1; - } - FreeLibrary(hinstLib); - } - } -#endif + hProcess = GetCurrentProcess(); + if( hProcess ){ + HINSTANCE hinstLib = LoadLibrary(TEXT("Kernel32.dll")); + if( NULL != hinstLib ){ + getProcessTimesAddr = + (GETPROCTIMES) GetProcAddress(hinstLib, "GetProcessTimes"); + if( NULL != getProcessTimesAddr ){ + return 1; + } + FreeLibrary(hinstLib); + } } - return 0; +#endif + } + return 0; } /* ** Begin timing an operation */ static void beginTimer(void){ - if( enableTimer && getProcessTimesAddr ){ - FILETIME ftCreation, ftExit; - getProcessTimesAddr(hProcess,&ftCreation,&ftExit, - &ftKernelBegin,&ftUserBegin); - ftWallBegin = timeOfDay(); - } + if( enableTimer && getProcessTimesAddr ){ + FILETIME ftCreation, ftExit; + getProcessTimesAddr(hProcess,&ftCreation,&ftExit, + &ftKernelBegin,&ftUserBegin); + ftWallBegin = timeOfDay(); + } } /* Return the difference of two FILETIME structs in seconds */ static double timeDiff(FILETIME *pStart, FILETIME *pEnd){ - sqlite_int64 i64Start = *((sqlite_int64 *) pStart); - sqlite_int64 i64End = *((sqlite_int64 *) pEnd); - return (double) ((i64End - i64Start) / 10000000.0); + sqlite_int64 i64Start = *((sqlite_int64 *) pStart); + sqlite_int64 i64End = *((sqlite_int64 *) pEnd); + return (double) ((i64End - i64Start) / 10000000.0); } /* ** Print the timing results. */ static void endTimer(void){ - if( enableTimer && getProcessTimesAddr){ - FILETIME ftCreation, ftExit, ftKernelEnd, ftUserEnd; - sqlite3_int64 ftWallEnd = timeOfDay(); - getProcessTimesAddr(hProcess,&ftCreation,&ftExit,&ftKernelEnd,&ftUserEnd); - printf("Run Time: real %.3f user %f sys %f\n", - (ftWallEnd - ftWallBegin)*0.001, - timeDiff(&ftUserBegin, &ftUserEnd), - timeDiff(&ftKernelBegin, &ftKernelEnd)); - } + if( enableTimer && getProcessTimesAddr){ + FILETIME ftCreation, ftExit, ftKernelEnd, ftUserEnd; + sqlite3_int64 ftWallEnd = timeOfDay(); + getProcessTimesAddr(hProcess,&ftCreation,&ftExit,&ftKernelEnd,&ftUserEnd); + printf("Run Time: real %.3f user %f sys %f\n", + (ftWallEnd - ftWallBegin)*0.001, + timeDiff(&ftUserBegin, &ftUserEnd), + timeDiff(&ftKernelBegin, &ftKernelEnd)); + } } #define BEGIN_TIMER beginTimer() @@ -474,18 +474,18 @@ static char continuePrompt[20]; /* Continuation prompt. default: " ...> " */ */ #if defined(_WIN32) || defined(WIN32) void utf8_printf(FILE *out, const char *zFormat, ...){ - va_list ap; - va_start(ap, zFormat); - if( stdout_is_console && (out==stdout || out==stderr) ){ - char *z1 = sqlite3_vmprintf(zFormat, ap); - char *z2 = sqlite3_win32_utf8_to_mbcs_v2(z1, 0); - sqlite3_free(z1); - fputs(z2, out); - sqlite3_free(z2); - }else{ - vfprintf(out, zFormat, ap); - } - va_end(ap); + va_list ap; + va_start(ap, zFormat); + if( stdout_is_console && (out==stdout || out==stderr) ){ + char *z1 = sqlite3_vmprintf(zFormat, ap); + char *z2 = sqlite3_win32_utf8_to_mbcs_v2(z1, 0); + sqlite3_free(z1); + fputs(z2, out); + sqlite3_free(z2); + }else{ + vfprintf(out, zFormat, ap); + } + va_end(ap); } #elif !defined(utf8_printf) # define utf8_printf fprintf @@ -501,8 +501,8 @@ void utf8_printf(FILE *out, const char *zFormat, ...){ /* Indicate out-of-memory and exit. */ static void shell_out_of_memory(void){ - raw_printf(stderr,"Error: out of memory\n"); - exit(1); + raw_printf(stderr,"Error: out of memory\n"); + exit(1); } #ifdef SQLITE_DEBUG @@ -511,11 +511,11 @@ static void shell_out_of_memory(void){ ** the OOM */ void shellOomFault(void){ - if( oomRepeat>0 ){ - oomRepeat--; - }else{ - oomCounter--; - } + if( oomRepeat>0 ){ + oomRepeat--; + }else{ + oomCounter--; + } } #endif /* SQLITE_DEBUG */ @@ -524,15 +524,15 @@ void shellOomFault(void){ ** Out-Of-Memory (OOM) errors for testing purposes. */ static void *oomMalloc(int nByte){ - if( oomCounter ){ - if( oomCounter==1 ){ - shellOomFault(); - return 0; - }else{ - oomCounter--; - } + if( oomCounter ){ + if( oomCounter==1 ){ + shellOomFault(); + return 0; + }else{ + oomCounter--; } - return defaultMalloc(nByte); + } + return defaultMalloc(nByte); } #endif /* SQLITE_DEBUG */ @@ -540,11 +540,11 @@ static void *oomMalloc(int nByte){ /* Register the OOM simulator. This must occur before any memory ** allocations */ static void registerOomSimulator(void){ - sqlite3_mem_methods mem; - sqlite3_config(SQLITE_CONFIG_GETMALLOC, &mem); - defaultMalloc = mem.xMalloc; - mem.xMalloc = oomMalloc; - sqlite3_config(SQLITE_CONFIG_MALLOC, &mem); + sqlite3_mem_methods mem; + sqlite3_config(SQLITE_CONFIG_GETMALLOC, &mem); + defaultMalloc = mem.xMalloc; + mem.xMalloc = oomMalloc; + sqlite3_config(SQLITE_CONFIG_MALLOC, &mem); } #endif @@ -563,14 +563,14 @@ static FILE *iotrace = 0; */ #ifdef SQLITE_ENABLE_IOTRACE static void SQLITE_CDECL iotracePrintf(const char *zFormat, ...){ - va_list ap; - char *z; - if( iotrace==0 ) return; - va_start(ap, zFormat); - z = sqlite3_vmprintf(zFormat, ap); - va_end(ap); - utf8_printf(iotrace, "%s", z); - sqlite3_free(z); + va_list ap; + char *z; + if( iotrace==0 ) return; + va_start(ap, zFormat); + z = sqlite3_vmprintf(zFormat, ap); + va_end(ap); + utf8_printf(iotrace, "%s", z); + sqlite3_free(z); } #endif @@ -581,25 +581,25 @@ static void SQLITE_CDECL iotracePrintf(const char *zFormat, ...){ ** since with %*.*s the width is measured in bytes, not characters. */ static void utf8_width_print(FILE *pOut, int w, const char *zUtf){ - int i; - int n; - int aw = w<0 ? -w : w; - for(i=n=0; zUtf[i]; i++){ - if( (zUtf[i]&0xc0)!=0x80 ){ - n++; - if( n==aw ){ - do{ i++; }while( (zUtf[i]&0xc0)==0x80 ); - break; - } - } - } - if( n>=aw ){ - utf8_printf(pOut, "%.*s", i, zUtf); - }else if( w<0 ){ - utf8_printf(pOut, "%*s%s", aw-n, "", zUtf); - }else{ - utf8_printf(pOut, "%s%*s", zUtf, aw-n, ""); + int i; + int n; + int aw = w<0 ? -w : w; + for(i=n=0; zUtf[i]; i++){ + if( (zUtf[i]&0xc0)!=0x80 ){ + n++; + if( n==aw ){ + do{ i++; }while( (zUtf[i]&0xc0)==0x80 ); + break; + } } + } + if( n>=aw ){ + utf8_printf(pOut, "%.*s", i, zUtf); + }else if( w<0 ){ + utf8_printf(pOut, "%*s%s", aw-n, "", zUtf); + }else{ + utf8_printf(pOut, "%s%*s", zUtf, aw-n, ""); + } } @@ -607,27 +607,27 @@ static void utf8_width_print(FILE *pOut, int w, const char *zUtf){ ** Determines if a string is a number of not. */ static int isNumber(const char *z, int *realnum){ - if( *z=='-' || *z=='+' ) z++; - if( !IsDigit(*z) ){ - return 0; - } + if( *z=='-' || *z=='+' ) z++; + if( !IsDigit(*z) ){ + return 0; + } + z++; + if( realnum ) *realnum = 0; + while( IsDigit(*z) ){ z++; } + if( *z=='.' ){ z++; - if( realnum ) *realnum = 0; + if( !IsDigit(*z) ) return 0; while( IsDigit(*z) ){ z++; } - if( *z=='.' ){ - z++; - if( !IsDigit(*z) ) return 0; - while( IsDigit(*z) ){ z++; } - if( realnum ) *realnum = 1; - } - if( *z=='e' || *z=='E' ){ - z++; - if( *z=='+' || *z=='-' ) z++; - if( !IsDigit(*z) ) return 0; - while( IsDigit(*z) ){ z++; } - if( realnum ) *realnum = 1; - } - return *z==0; + if( realnum ) *realnum = 1; + } + if( *z=='e' || *z=='E' ){ + z++; + if( *z=='+' || *z=='-' ) z++; + if( !IsDigit(*z) ) return 0; + while( IsDigit(*z) ){ z++; } + if( realnum ) *realnum = 1; + } + return *z==0; } /* @@ -635,9 +635,9 @@ static int isNumber(const char *z, int *realnum){ ** lower 30 bits of a 32-bit signed integer. */ static int strlen30(const char *z){ - const char *z2 = z; - while( *z2 ){ z2++; } - return 0x3fffffff & (int)(z2 - z); + const char *z2 = z; + while( *z2 ){ z2++; } + return 0x3fffffff & (int)(z2 - z); } /* @@ -645,11 +645,11 @@ static int strlen30(const char *z){ ** count as a single character. */ static int strlenChar(const char *z){ - int n = 0; - while( *z ){ - if( (0xc0&*(z++))!=0x80 ) n++; - } - return n; + int n = 0; + while( *z ){ + if( (0xc0&*(z++))!=0x80 ) n++; + } + return n; } /* @@ -659,29 +659,29 @@ static int strlenChar(const char *z){ */ static FILE * openChrSource(const char *zFile){ #ifdef _WIN32 - struct _stat x = {0}; + struct _stat x = {0}; # define STAT_CHR_SRC(mode) ((mode & (_S_IFCHR|_S_IFIFO|_S_IFREG))!=0) - /* On Windows, open first, then check the stream nature. This order + /* On Windows, open first, then check the stream nature. This order ** is necessary because _stat() and sibs, when checking a named pipe, ** effectively break the pipe as its supplier sees it. */ - FILE *rv = fopen(zFile, "rb"); - if( rv==0 ) return 0; - if( _fstat(_fileno(rv), &x) != 0 - || !STAT_CHR_SRC(x.st_mode)){ - fclose(rv); - rv = 0; - } - return rv; + FILE *rv = fopen(zFile, "rb"); + if( rv==0 ) return 0; + if( _fstat(_fileno(rv), &x) != 0 + || !STAT_CHR_SRC(x.st_mode)){ + fclose(rv); + rv = 0; + } + return rv; #else - struct stat x = {0}; - int rc = stat(zFile, &x); + struct stat x = {0}; + int rc = stat(zFile, &x); # define STAT_CHR_SRC(mode) (S_ISREG(mode)||S_ISFIFO(mode)||S_ISCHR(mode)) - if( rc!=0 ) return 0; - if( STAT_CHR_SRC(x.st_mode) ){ - return fopen(zFile, "rb"); - }else{ - return 0; - } + if( rc!=0 ) return 0; + if( STAT_CHR_SRC(x.st_mode) ){ + return fopen(zFile, "rb"); + }else{ + return 0; + } #endif #undef STAT_CHR_SRC } @@ -696,48 +696,48 @@ static FILE * openChrSource(const char *zFile){ ** a previous call to this routine that may be reused. */ static char *local_getline(char *zLine, FILE *in){ - int nLine = zLine==0 ? 0 : 100; - int n = 0; - - while( 1 ){ - if( n+100>nLine ){ - nLine = nLine*2 + 100; - zLine = realloc(zLine, nLine); - if( zLine==0 ) shell_out_of_memory(); - } - if( fgets(&zLine[n], nLine - n, in)==0 ){ - if( n==0 ){ - free(zLine); - return 0; - } - zLine[n] = 0; - break; - } - while( zLine[n] ) n++; - if( n>0 && zLine[n-1]=='\n' ){ - n--; - if( n>0 && zLine[n-1]=='\r' ) n--; - zLine[n] = 0; - break; - } - } + int nLine = zLine==0 ? 0 : 100; + int n = 0; + + while( 1 ){ + if( n+100>nLine ){ + nLine = nLine*2 + 100; + zLine = realloc(zLine, nLine); + if( zLine==0 ) shell_out_of_memory(); + } + if( fgets(&zLine[n], nLine - n, in)==0 ){ + if( n==0 ){ + free(zLine); + return 0; + } + zLine[n] = 0; + break; + } + while( zLine[n] ) n++; + if( n>0 && zLine[n-1]=='\n' ){ + n--; + if( n>0 && zLine[n-1]=='\r' ) n--; + zLine[n] = 0; + break; + } + } #if defined(_WIN32) || defined(WIN32) - /* For interactive input on Windows systems, translate the + /* For interactive input on Windows systems, translate the ** multi-byte characterset characters into UTF-8. */ - if( stdin_is_interactive && in==stdin ){ - char *zTrans = sqlite3_win32_mbcs_to_utf8_v2(zLine, 0); - if( zTrans ){ - int nTrans = strlen30(zTrans)+1; - if( nTrans>nLine ){ - zLine = realloc(zLine, nTrans); - if( zLine==0 ) shell_out_of_memory(); - } - memcpy(zLine, zTrans, nTrans); - sqlite3_free(zTrans); - } - } + if( stdin_is_interactive && in==stdin ){ + char *zTrans = sqlite3_win32_mbcs_to_utf8_v2(zLine, 0); + if( zTrans ){ + int nTrans = strlen30(zTrans)+1; + if( nTrans>nLine ){ + zLine = realloc(zLine, nTrans); + if( zLine==0 ) shell_out_of_memory(); + } + memcpy(zLine, zTrans, nTrans); + sqlite3_free(zTrans); + } + } #endif /* defined(_WIN32) || defined(WIN32) */ - return zLine; + return zLine; } /* @@ -755,23 +755,23 @@ static char *local_getline(char *zLine, FILE *in){ ** zPrior argument for reuse. */ static char *one_input_line(FILE *in, char *zPrior, int isContinuation){ - char *zPrompt; - char *zResult; - if( in!=0 ){ - zResult = local_getline(zPrior, in); - }else{ - zPrompt = isContinuation ? continuePrompt : mainPrompt; + char *zPrompt; + char *zResult; + if( in!=0 ){ + zResult = local_getline(zPrior, in); + }else{ + zPrompt = isContinuation ? continuePrompt : mainPrompt; #if SHELL_USE_LOCAL_GETLINE - printf("%s", zPrompt); - fflush(stdout); - zResult = local_getline(zPrior, stdin); + printf("%s", zPrompt); + fflush(stdout); + zResult = local_getline(zPrior, stdin); #else - free(zPrior); - zResult = shell_readline(zPrompt); - if( zResult && *zResult ) shell_add_history(zResult); + free(zPrior); + zResult = shell_readline(zPrompt); + if( zResult && *zResult ) shell_add_history(zResult); #endif - } - return zResult; + } + return zResult; } @@ -780,56 +780,56 @@ static char *one_input_line(FILE *in, char *zPrior, int isContinuation){ ** is not a hex digit. */ static int hexDigitValue(char c){ - if( c>='0' && c<='9' ) return c - '0'; - if( c>='a' && c<='f' ) return c - 'a' + 10; - if( c>='A' && c<='F' ) return c - 'A' + 10; - return -1; + if( c>='0' && c<='9' ) return c - '0'; + if( c>='a' && c<='f' ) return c - 'a' + 10; + if( c>='A' && c<='F' ) return c - 'A' + 10; + return -1; } /* ** Interpret zArg as an integer value, possibly with suffixes. */ static sqlite3_int64 integerValue(const char *zArg){ - sqlite3_int64 v = 0; - static const struct { char *zSuffix; int iMult; } aMult[] = { - { "KiB", 1024 }, - { "MiB", 1024*1024 }, - { "GiB", 1024*1024*1024 }, - { "KB", 1000 }, - { "MB", 1000000 }, - { "GB", 1000000000 }, - { "K", 1000 }, - { "M", 1000000 }, - { "G", 1000000000 }, - }; - int i; - int isNeg = 0; - if( zArg[0]=='-' ){ - isNeg = 1; - zArg++; - }else if( zArg[0]=='+' ){ - zArg++; - } - if( zArg[0]=='0' && zArg[1]=='x' ){ - int x; - zArg += 2; - while( (x = hexDigitValue(zArg[0]))>=0 ){ - v = (v<<4) + x; - zArg++; - } - }else{ - while( IsDigit(zArg[0]) ){ - v = v*10 + zArg[0] - '0'; - zArg++; - } - } - for(i=0; i=0 ){ + v = (v<<4) + x; + zArg++; + } + }else{ + while( IsDigit(zArg[0]) ){ + v = v*10 + zArg[0] - '0'; + zArg++; + } + } + for(i=0; iz); - initText(p); + free(p->z); + initText(p); } /* zIn is either a pointer to a NULL-terminated string in memory obtained @@ -862,39 +862,39 @@ static void freeText(ShellText *p){ ** quote character for zAppend. */ static void appendText(ShellText *p, char const *zAppend, char quote){ - int len; - int i; - int nAppend = strlen30(zAppend); - - len = nAppend+p->n+1; - if( quote ){ - len += 2; - for(i=0; iz==0 || p->n+len>=p->nAlloc ){ - p->nAlloc = p->nAlloc*2 + len + 20; - p->z = realloc(p->z, p->nAlloc); - if( p->z==0 ) shell_out_of_memory(); - } - - if( quote ){ - char *zCsr = p->z+p->n; - *zCsr++ = quote; - for(i=0; in = (int)(zCsr - p->z); - *zCsr = '\0'; - }else{ - memcpy(p->z+p->n, zAppend, nAppend); - p->n += nAppend; - p->z[p->n] = '\0'; - } + int len; + int i; + int nAppend = strlen30(zAppend); + + len = nAppend+p->n+1; + if( quote ){ + len += 2; + for(i=0; iz==0 || p->n+len>=p->nAlloc ){ + p->nAlloc = p->nAlloc*2 + len + 20; + p->z = realloc(p->z, p->nAlloc); + if( p->z==0 ) shell_out_of_memory(); + } + + if( quote ){ + char *zCsr = p->z+p->n; + *zCsr++ = quote; + for(i=0; in = (int)(zCsr - p->z); + *zCsr = '\0'; + }else{ + memcpy(p->z+p->n, zAppend, nAppend); + p->n += nAppend; + p->z[p->n] = '\0'; + } } /* @@ -906,12 +906,12 @@ static void appendText(ShellText *p, char const *zAppend, char quote){ ** Return '"' if quoting is required. Return 0 if no quoting is required. */ static char quoteChar(const char *zName){ - int i; - if( !isalpha((unsigned char)zName[0]) && zName[0]!='_' ) return '"'; - for(i=0; zName[i]; i++){ - if( !isalnum((unsigned char)zName[i]) && zName[i]!='_' ) return '"'; - } - return sqlite3_keyword_check(zName, i) ? '"' : 0; + int i; + if( !isalpha((unsigned char)zName[0]) && zName[0]!='_' ) return '"'; + for(i=0; zName[i]; i++){ + if( !isalnum((unsigned char)zName[i]) && zName[i]!='_' ) return '"'; + } + return sqlite3_keyword_check(zName, i) ? '"' : 0; } /* @@ -919,45 +919,45 @@ static char quoteChar(const char *zName){ ** of the view, virtual table, or table valued function zSchema.zName. */ static char *shellFakeSchema( - sqlite3 *db, /* The database connection containing the vtab */ - const char *zSchema, /* Schema of the database holding the vtab */ - const char *zName /* The name of the virtual table */ + sqlite3 *db, /* The database connection containing the vtab */ + const char *zSchema, /* Schema of the database holding the vtab */ + const char *zName /* The name of the virtual table */ ){ - sqlite3_stmt *pStmt = 0; - char *zSql; - ShellText s; - char cQuote; - char *zDiv = "("; - int nRow = 0; - - zSql = sqlite3_mprintf("PRAGMA \"%w\".table_info=%Q;", - zSchema ? zSchema : "main", zName); - sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0); - sqlite3_free(zSql); - initText(&s); - if( zSchema ){ - cQuote = quoteChar(zSchema); - if( cQuote && sqlite3_stricmp(zSchema,"temp")==0 ) cQuote = 0; - appendText(&s, zSchema, cQuote); - appendText(&s, ".", 0); - } - cQuote = quoteChar(zName); - appendText(&s, zName, cQuote); - while( sqlite3_step(pStmt)==SQLITE_ROW ){ - const char *zCol = (const char*)sqlite3_column_text(pStmt, 1); - nRow++; - appendText(&s, zDiv, 0); - zDiv = ","; - cQuote = quoteChar(zCol); - appendText(&s, zCol, cQuote); - } - appendText(&s, ")", 0); - sqlite3_finalize(pStmt); - if( nRow==0 ){ - freeText(&s); - s.z = 0; - } - return s.z; + sqlite3_stmt *pStmt = 0; + char *zSql; + ShellText s; + char cQuote; + char *zDiv = "("; + int nRow = 0; + + zSql = sqlite3_mprintf("PRAGMA \"%w\".table_info=%Q;", + zSchema ? zSchema : "main", zName); + sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0); + sqlite3_free(zSql); + initText(&s); + if( zSchema ){ + cQuote = quoteChar(zSchema); + if( cQuote && sqlite3_stricmp(zSchema,"temp")==0 ) cQuote = 0; + appendText(&s, zSchema, cQuote); + appendText(&s, ".", 0); + } + cQuote = quoteChar(zName); + appendText(&s, zName, cQuote); + while( sqlite3_step(pStmt)==SQLITE_ROW ){ + const char *zCol = (const char*)sqlite3_column_text(pStmt, 1); + nRow++; + appendText(&s, zDiv, 0); + zDiv = ","; + cQuote = quoteChar(zCol); + appendText(&s, zCol, cQuote); + } + appendText(&s, ")", 0); + sqlite3_finalize(pStmt); + if( nRow==0 ){ + freeText(&s); + s.z = 0; + } + return s.z; } /* @@ -967,18 +967,18 @@ static char *shellFakeSchema( ** table X. */ static void shellModuleSchema( - sqlite3_context *pCtx, - int nVal, - sqlite3_value **apVal + sqlite3_context *pCtx, + int nVal, + sqlite3_value **apVal ){ - const char *zName = (const char*)sqlite3_value_text(apVal[0]); - char *zFake = shellFakeSchema(sqlite3_context_db_handle(pCtx), 0, zName); - UNUSED_PARAMETER(nVal); - if( zFake ){ - sqlite3_result_text(pCtx, sqlite3_mprintf("/* %s */", zFake), - -1, sqlite3_free); - free(zFake); - } + const char *zName = (const char*)sqlite3_value_text(apVal[0]); + char *zFake = shellFakeSchema(sqlite3_context_db_handle(pCtx), 0, zName); + UNUSED_PARAMETER(nVal); + if( zFake ){ + sqlite3_result_text(pCtx, sqlite3_mprintf("/* %s */", zFake), + -1, sqlite3_free); + free(zFake); + } } /* @@ -1001,57 +1001,57 @@ static void shellModuleSchema( ** attached databases into the middle of the sqlite_schema.sql field. */ static void shellAddSchemaName( - sqlite3_context *pCtx, - int nVal, - sqlite3_value **apVal + sqlite3_context *pCtx, + int nVal, + sqlite3_value **apVal ){ - static const char *aPrefix[] = { - "TABLE", - "INDEX", - "UNIQUE INDEX", - "VIEW", - "TRIGGER", - "VIRTUAL TABLE" - }; - int i = 0; - const char *zIn = (const char*)sqlite3_value_text(apVal[0]); - const char *zSchema = (const char*)sqlite3_value_text(apVal[1]); - const char *zName = (const char*)sqlite3_value_text(apVal[2]); - sqlite3 *db = sqlite3_context_db_handle(pCtx); - UNUSED_PARAMETER(nVal); - if( zIn!=0 && strncmp(zIn, "CREATE ", 7)==0 ){ - for(i=0; idwSize ){ - /* + memset(value, 0, sizeof(value)); + dwRet = GetEnvironmentVariableA(name, value, dwSize); + if( dwRet==0 || dwRet>dwSize ){ + /* ** The function call to GetEnvironmentVariableA() failed -OR- ** the buffer is not large enough. Either way, return NULL. */ - return 0; - }else{ - /* + return 0; + }else{ + /* ** The function call to GetEnvironmentVariableA() succeeded ** -AND- the buffer contains the entire value. */ - return value; - } + return value; + } } /* ** Implementation of the POSIX opendir() function using the MSVCRT. */ LPDIR opendir( - const char *dirname + const char *dirname ){ - struct _finddata_t data; - LPDIR dirp = (LPDIR)sqlite3_malloc(sizeof(DIR)); - SIZE_T namesize = sizeof(data.name) / sizeof(data.name[0]); - - if( dirp==NULL ) return NULL; - memset(dirp, 0, sizeof(DIR)); + struct _finddata_t data; + LPDIR dirp = (LPDIR)sqlite3_malloc(sizeof(DIR)); + SIZE_T namesize = sizeof(data.name) / sizeof(data.name[0]); - /* TODO: Remove this if Unix-style root paths are not used. */ - if( sqlite3_stricmp(dirname, "/")==0 ){ - dirname = windirent_getenv("SystemDrive"); - } + if( dirp==NULL ) return NULL; + memset(dirp, 0, sizeof(DIR)); - memset(&data, 0, sizeof(struct _finddata_t)); - _snprintf(data.name, namesize, "%s\\*", dirname); - dirp->d_handle = _findfirst(data.name, &data); + /* TODO: Remove this if Unix-style root paths are not used. */ + if( sqlite3_stricmp(dirname, "/")==0 ){ + dirname = windirent_getenv("SystemDrive"); + } - if( dirp->d_handle==BAD_INTPTR_T ){ - closedir(dirp); - return NULL; - } + memset(&data, 0, sizeof(struct _finddata_t)); + _snprintf(data.name, namesize, "%s\\*", dirname); + dirp->d_handle = _findfirst(data.name, &data); - /* TODO: Remove this block to allow hidden and/or system files. */ - if( is_filtered(data) ){ - next: + if( dirp->d_handle==BAD_INTPTR_T ){ + closedir(dirp); + return NULL; + } - memset(&data, 0, sizeof(struct _finddata_t)); - if( _findnext(dirp->d_handle, &data)==-1 ){ - closedir(dirp); - return NULL; - } + /* TODO: Remove this block to allow hidden and/or system files. */ + if( is_filtered(data) ){ +next: - /* TODO: Remove this block to allow hidden and/or system files. */ - if( is_filtered(data) ) goto next; + memset(&data, 0, sizeof(struct _finddata_t)); + if( _findnext(dirp->d_handle, &data)==-1 ){ + closedir(dirp); + return NULL; } - dirp->d_first.d_attributes = data.attrib; - strncpy(dirp->d_first.d_name, data.name, NAME_MAX); - dirp->d_first.d_name[NAME_MAX] = '\0'; + /* TODO: Remove this block to allow hidden and/or system files. */ + if( is_filtered(data) ) goto next; + } + + dirp->d_first.d_attributes = data.attrib; + strncpy(dirp->d_first.d_name, data.name, NAME_MAX); + dirp->d_first.d_name[NAME_MAX] = '\0'; - return dirp; + return dirp; } /* ** Implementation of the POSIX readdir() function using the MSVCRT. */ LPDIRENT readdir( - LPDIR dirp + LPDIR dirp ){ - struct _finddata_t data; + struct _finddata_t data; - if( dirp==NULL ) return NULL; + if( dirp==NULL ) return NULL; - if( dirp->d_first.d_ino==0 ){ - dirp->d_first.d_ino++; - dirp->d_next.d_ino++; + if( dirp->d_first.d_ino==0 ){ + dirp->d_first.d_ino++; + dirp->d_next.d_ino++; - return &dirp->d_first; - } + return &dirp->d_first; + } next: - memset(&data, 0, sizeof(struct _finddata_t)); - if( _findnext(dirp->d_handle, &data)==-1 ) return NULL; + memset(&data, 0, sizeof(struct _finddata_t)); + if( _findnext(dirp->d_handle, &data)==-1 ) return NULL; - /* TODO: Remove this block to allow hidden and/or system files. */ - if( is_filtered(data) ) goto next; + /* TODO: Remove this block to allow hidden and/or system files. */ + if( is_filtered(data) ) goto next; - dirp->d_next.d_ino++; - dirp->d_next.d_attributes = data.attrib; - strncpy(dirp->d_next.d_name, data.name, NAME_MAX); - dirp->d_next.d_name[NAME_MAX] = '\0'; + dirp->d_next.d_ino++; + dirp->d_next.d_attributes = data.attrib; + strncpy(dirp->d_next.d_name, data.name, NAME_MAX); + dirp->d_next.d_name[NAME_MAX] = '\0'; - return &dirp->d_next; + return &dirp->d_next; } /* ** Implementation of the POSIX readdir_r() function using the MSVCRT. */ INT readdir_r( - LPDIR dirp, - LPDIRENT entry, - LPDIRENT *result + LPDIR dirp, + LPDIRENT entry, + LPDIRENT *result ){ - struct _finddata_t data; + struct _finddata_t data; - if( dirp==NULL ) return EBADF; + if( dirp==NULL ) return EBADF; - if( dirp->d_first.d_ino==0 ){ - dirp->d_first.d_ino++; - dirp->d_next.d_ino++; + if( dirp->d_first.d_ino==0 ){ + dirp->d_first.d_ino++; + dirp->d_next.d_ino++; - entry->d_ino = dirp->d_first.d_ino; - entry->d_attributes = dirp->d_first.d_attributes; - strncpy(entry->d_name, dirp->d_first.d_name, NAME_MAX); - entry->d_name[NAME_MAX] = '\0'; + entry->d_ino = dirp->d_first.d_ino; + entry->d_attributes = dirp->d_first.d_attributes; + strncpy(entry->d_name, dirp->d_first.d_name, NAME_MAX); + entry->d_name[NAME_MAX] = '\0'; - *result = entry; - return 0; - } + *result = entry; + return 0; + } next: - memset(&data, 0, sizeof(struct _finddata_t)); - if( _findnext(dirp->d_handle, &data)==-1 ){ - *result = NULL; - return ENOENT; - } + memset(&data, 0, sizeof(struct _finddata_t)); + if( _findnext(dirp->d_handle, &data)==-1 ){ + *result = NULL; + return ENOENT; + } - /* TODO: Remove this block to allow hidden and/or system files. */ - if( is_filtered(data) ) goto next; + /* TODO: Remove this block to allow hidden and/or system files. */ + if( is_filtered(data) ) goto next; - entry->d_ino = (ino_t)-1; /* not available */ - entry->d_attributes = data.attrib; - strncpy(entry->d_name, data.name, NAME_MAX); - entry->d_name[NAME_MAX] = '\0'; + entry->d_ino = (ino_t)-1; /* not available */ + entry->d_attributes = data.attrib; + strncpy(entry->d_name, data.name, NAME_MAX); + entry->d_name[NAME_MAX] = '\0'; - *result = entry; - return 0; + *result = entry; + return 0; } /* ** Implementation of the POSIX closedir() function using the MSVCRT. */ INT closedir( - LPDIR dirp + LPDIR dirp ){ - INT result = 0; + INT result = 0; - if( dirp==NULL ) return EINVAL; + if( dirp==NULL ) return EINVAL; - if( dirp->d_handle!=NULL_INTPTR_T && dirp->d_handle!=BAD_INTPTR_T ){ - result = _findclose(dirp->d_handle); - } + if( dirp->d_handle!=NULL_INTPTR_T && dirp->d_handle!=BAD_INTPTR_T ){ + result = _findclose(dirp->d_handle); + } - sqlite3_free(dirp); - return result; + sqlite3_free(dirp); + return result; } #endif /* defined(WIN32) && defined(_MSC_VER) */ @@ -1492,37 +1492,37 @@ SQLITE_EXTENSION_INIT1 */ typedef struct SHA3Context SHA3Context; struct SHA3Context { - union { - u64 s[25]; /* Keccak state. 5x5 lines of 64 bits each */ - unsigned char x[1600]; /* ... or 1600 bytes */ - } u; - unsigned nRate; /* Bytes of input accepted per Keccak iteration */ - unsigned nLoaded; /* Input bytes loaded into u.x[] so far this cycle */ - unsigned ixMask; /* Insert next input into u.x[nLoaded^ixMask]. */ + union { + u64 s[25]; /* Keccak state. 5x5 lines of 64 bits each */ + unsigned char x[1600]; /* ... or 1600 bytes */ + } u; + unsigned nRate; /* Bytes of input accepted per Keccak iteration */ + unsigned nLoaded; /* Input bytes loaded into u.x[] so far this cycle */ + unsigned ixMask; /* Insert next input into u.x[nLoaded^ixMask]. */ }; /* ** A single step of the Keccak mixing function for a 1600-bit state */ static void KeccakF1600Step(SHA3Context *p){ - int i; - u64 b0, b1, b2, b3, b4; - u64 c0, c1, c2, c3, c4; - u64 d0, d1, d2, d3, d4; - static const u64 RC[] = { - 0x0000000000000001ULL, 0x0000000000008082ULL, - 0x800000000000808aULL, 0x8000000080008000ULL, - 0x000000000000808bULL, 0x0000000080000001ULL, - 0x8000000080008081ULL, 0x8000000000008009ULL, - 0x000000000000008aULL, 0x0000000000000088ULL, - 0x0000000080008009ULL, 0x000000008000000aULL, - 0x000000008000808bULL, 0x800000000000008bULL, - 0x8000000000008089ULL, 0x8000000000008003ULL, - 0x8000000000008002ULL, 0x8000000000000080ULL, - 0x000000000000800aULL, 0x800000008000000aULL, - 0x8000000080008081ULL, 0x8000000000008080ULL, - 0x0000000080000001ULL, 0x8000000080008008ULL - }; + int i; + u64 b0, b1, b2, b3, b4; + u64 c0, c1, c2, c3, c4; + u64 d0, d1, d2, d3, d4; + static const u64 RC[] = { + 0x0000000000000001ULL, 0x0000000000008082ULL, + 0x800000000000808aULL, 0x8000000080008000ULL, + 0x000000000000808bULL, 0x0000000080000001ULL, + 0x8000000080008081ULL, 0x8000000000008009ULL, + 0x000000000000008aULL, 0x0000000000000088ULL, + 0x0000000080008009ULL, 0x000000008000000aULL, + 0x000000008000808bULL, 0x800000000000008bULL, + 0x8000000000008089ULL, 0x8000000000008003ULL, + 0x8000000000008002ULL, 0x8000000000000080ULL, + 0x000000000000800aULL, 0x800000008000000aULL, + 0x8000000080008081ULL, 0x8000000000008080ULL, + 0x0000000080000001ULL, 0x8000000080008008ULL + }; # define a00 (p->u.s[0]) # define a01 (p->u.s[1]) # define a02 (p->u.s[2]) @@ -1550,275 +1550,275 @@ static void KeccakF1600Step(SHA3Context *p){ # define a44 (p->u.s[24]) # define ROL64(a,x) ((a<>(64-x))) - for(i=0; i<24; i+=4){ - c0 = a00^a10^a20^a30^a40; - c1 = a01^a11^a21^a31^a41; - c2 = a02^a12^a22^a32^a42; - c3 = a03^a13^a23^a33^a43; - c4 = a04^a14^a24^a34^a44; - d0 = c4^ROL64(c1, 1); - d1 = c0^ROL64(c2, 1); - d2 = c1^ROL64(c3, 1); - d3 = c2^ROL64(c4, 1); - d4 = c3^ROL64(c0, 1); - - b0 = (a00^d0); - b1 = ROL64((a11^d1), 44); - b2 = ROL64((a22^d2), 43); - b3 = ROL64((a33^d3), 21); - b4 = ROL64((a44^d4), 14); - a00 = b0 ^((~b1)& b2 ); - a00 ^= RC[i]; - a11 = b1 ^((~b2)& b3 ); - a22 = b2 ^((~b3)& b4 ); - a33 = b3 ^((~b4)& b0 ); - a44 = b4 ^((~b0)& b1 ); - - b2 = ROL64((a20^d0), 3); - b3 = ROL64((a31^d1), 45); - b4 = ROL64((a42^d2), 61); - b0 = ROL64((a03^d3), 28); - b1 = ROL64((a14^d4), 20); - a20 = b0 ^((~b1)& b2 ); - a31 = b1 ^((~b2)& b3 ); - a42 = b2 ^((~b3)& b4 ); - a03 = b3 ^((~b4)& b0 ); - a14 = b4 ^((~b0)& b1 ); - - b4 = ROL64((a40^d0), 18); - b0 = ROL64((a01^d1), 1); - b1 = ROL64((a12^d2), 6); - b2 = ROL64((a23^d3), 25); - b3 = ROL64((a34^d4), 8); - a40 = b0 ^((~b1)& b2 ); - a01 = b1 ^((~b2)& b3 ); - a12 = b2 ^((~b3)& b4 ); - a23 = b3 ^((~b4)& b0 ); - a34 = b4 ^((~b0)& b1 ); - - b1 = ROL64((a10^d0), 36); - b2 = ROL64((a21^d1), 10); - b3 = ROL64((a32^d2), 15); - b4 = ROL64((a43^d3), 56); - b0 = ROL64((a04^d4), 27); - a10 = b0 ^((~b1)& b2 ); - a21 = b1 ^((~b2)& b3 ); - a32 = b2 ^((~b3)& b4 ); - a43 = b3 ^((~b4)& b0 ); - a04 = b4 ^((~b0)& b1 ); - - b3 = ROL64((a30^d0), 41); - b4 = ROL64((a41^d1), 2); - b0 = ROL64((a02^d2), 62); - b1 = ROL64((a13^d3), 55); - b2 = ROL64((a24^d4), 39); - a30 = b0 ^((~b1)& b2 ); - a41 = b1 ^((~b2)& b3 ); - a02 = b2 ^((~b3)& b4 ); - a13 = b3 ^((~b4)& b0 ); - a24 = b4 ^((~b0)& b1 ); - - c0 = a00^a20^a40^a10^a30; - c1 = a11^a31^a01^a21^a41; - c2 = a22^a42^a12^a32^a02; - c3 = a33^a03^a23^a43^a13; - c4 = a44^a14^a34^a04^a24; - d0 = c4^ROL64(c1, 1); - d1 = c0^ROL64(c2, 1); - d2 = c1^ROL64(c3, 1); - d3 = c2^ROL64(c4, 1); - d4 = c3^ROL64(c0, 1); - - b0 = (a00^d0); - b1 = ROL64((a31^d1), 44); - b2 = ROL64((a12^d2), 43); - b3 = ROL64((a43^d3), 21); - b4 = ROL64((a24^d4), 14); - a00 = b0 ^((~b1)& b2 ); - a00 ^= RC[i+1]; - a31 = b1 ^((~b2)& b3 ); - a12 = b2 ^((~b3)& b4 ); - a43 = b3 ^((~b4)& b0 ); - a24 = b4 ^((~b0)& b1 ); - - b2 = ROL64((a40^d0), 3); - b3 = ROL64((a21^d1), 45); - b4 = ROL64((a02^d2), 61); - b0 = ROL64((a33^d3), 28); - b1 = ROL64((a14^d4), 20); - a40 = b0 ^((~b1)& b2 ); - a21 = b1 ^((~b2)& b3 ); - a02 = b2 ^((~b3)& b4 ); - a33 = b3 ^((~b4)& b0 ); - a14 = b4 ^((~b0)& b1 ); - - b4 = ROL64((a30^d0), 18); - b0 = ROL64((a11^d1), 1); - b1 = ROL64((a42^d2), 6); - b2 = ROL64((a23^d3), 25); - b3 = ROL64((a04^d4), 8); - a30 = b0 ^((~b1)& b2 ); - a11 = b1 ^((~b2)& b3 ); - a42 = b2 ^((~b3)& b4 ); - a23 = b3 ^((~b4)& b0 ); - a04 = b4 ^((~b0)& b1 ); - - b1 = ROL64((a20^d0), 36); - b2 = ROL64((a01^d1), 10); - b3 = ROL64((a32^d2), 15); - b4 = ROL64((a13^d3), 56); - b0 = ROL64((a44^d4), 27); - a20 = b0 ^((~b1)& b2 ); - a01 = b1 ^((~b2)& b3 ); - a32 = b2 ^((~b3)& b4 ); - a13 = b3 ^((~b4)& b0 ); - a44 = b4 ^((~b0)& b1 ); - - b3 = ROL64((a10^d0), 41); - b4 = ROL64((a41^d1), 2); - b0 = ROL64((a22^d2), 62); - b1 = ROL64((a03^d3), 55); - b2 = ROL64((a34^d4), 39); - a10 = b0 ^((~b1)& b2 ); - a41 = b1 ^((~b2)& b3 ); - a22 = b2 ^((~b3)& b4 ); - a03 = b3 ^((~b4)& b0 ); - a34 = b4 ^((~b0)& b1 ); - - c0 = a00^a40^a30^a20^a10; - c1 = a31^a21^a11^a01^a41; - c2 = a12^a02^a42^a32^a22; - c3 = a43^a33^a23^a13^a03; - c4 = a24^a14^a04^a44^a34; - d0 = c4^ROL64(c1, 1); - d1 = c0^ROL64(c2, 1); - d2 = c1^ROL64(c3, 1); - d3 = c2^ROL64(c4, 1); - d4 = c3^ROL64(c0, 1); - - b0 = (a00^d0); - b1 = ROL64((a21^d1), 44); - b2 = ROL64((a42^d2), 43); - b3 = ROL64((a13^d3), 21); - b4 = ROL64((a34^d4), 14); - a00 = b0 ^((~b1)& b2 ); - a00 ^= RC[i+2]; - a21 = b1 ^((~b2)& b3 ); - a42 = b2 ^((~b3)& b4 ); - a13 = b3 ^((~b4)& b0 ); - a34 = b4 ^((~b0)& b1 ); - - b2 = ROL64((a30^d0), 3); - b3 = ROL64((a01^d1), 45); - b4 = ROL64((a22^d2), 61); - b0 = ROL64((a43^d3), 28); - b1 = ROL64((a14^d4), 20); - a30 = b0 ^((~b1)& b2 ); - a01 = b1 ^((~b2)& b3 ); - a22 = b2 ^((~b3)& b4 ); - a43 = b3 ^((~b4)& b0 ); - a14 = b4 ^((~b0)& b1 ); - - b4 = ROL64((a10^d0), 18); - b0 = ROL64((a31^d1), 1); - b1 = ROL64((a02^d2), 6); - b2 = ROL64((a23^d3), 25); - b3 = ROL64((a44^d4), 8); - a10 = b0 ^((~b1)& b2 ); - a31 = b1 ^((~b2)& b3 ); - a02 = b2 ^((~b3)& b4 ); - a23 = b3 ^((~b4)& b0 ); - a44 = b4 ^((~b0)& b1 ); - - b1 = ROL64((a40^d0), 36); - b2 = ROL64((a11^d1), 10); - b3 = ROL64((a32^d2), 15); - b4 = ROL64((a03^d3), 56); - b0 = ROL64((a24^d4), 27); - a40 = b0 ^((~b1)& b2 ); - a11 = b1 ^((~b2)& b3 ); - a32 = b2 ^((~b3)& b4 ); - a03 = b3 ^((~b4)& b0 ); - a24 = b4 ^((~b0)& b1 ); - - b3 = ROL64((a20^d0), 41); - b4 = ROL64((a41^d1), 2); - b0 = ROL64((a12^d2), 62); - b1 = ROL64((a33^d3), 55); - b2 = ROL64((a04^d4), 39); - a20 = b0 ^((~b1)& b2 ); - a41 = b1 ^((~b2)& b3 ); - a12 = b2 ^((~b3)& b4 ); - a33 = b3 ^((~b4)& b0 ); - a04 = b4 ^((~b0)& b1 ); - - c0 = a00^a30^a10^a40^a20; - c1 = a21^a01^a31^a11^a41; - c2 = a42^a22^a02^a32^a12; - c3 = a13^a43^a23^a03^a33; - c4 = a34^a14^a44^a24^a04; - d0 = c4^ROL64(c1, 1); - d1 = c0^ROL64(c2, 1); - d2 = c1^ROL64(c3, 1); - d3 = c2^ROL64(c4, 1); - d4 = c3^ROL64(c0, 1); - - b0 = (a00^d0); - b1 = ROL64((a01^d1), 44); - b2 = ROL64((a02^d2), 43); - b3 = ROL64((a03^d3), 21); - b4 = ROL64((a04^d4), 14); - a00 = b0 ^((~b1)& b2 ); - a00 ^= RC[i+3]; - a01 = b1 ^((~b2)& b3 ); - a02 = b2 ^((~b3)& b4 ); - a03 = b3 ^((~b4)& b0 ); - a04 = b4 ^((~b0)& b1 ); - - b2 = ROL64((a10^d0), 3); - b3 = ROL64((a11^d1), 45); - b4 = ROL64((a12^d2), 61); - b0 = ROL64((a13^d3), 28); - b1 = ROL64((a14^d4), 20); - a10 = b0 ^((~b1)& b2 ); - a11 = b1 ^((~b2)& b3 ); - a12 = b2 ^((~b3)& b4 ); - a13 = b3 ^((~b4)& b0 ); - a14 = b4 ^((~b0)& b1 ); - - b4 = ROL64((a20^d0), 18); - b0 = ROL64((a21^d1), 1); - b1 = ROL64((a22^d2), 6); - b2 = ROL64((a23^d3), 25); - b3 = ROL64((a24^d4), 8); - a20 = b0 ^((~b1)& b2 ); - a21 = b1 ^((~b2)& b3 ); - a22 = b2 ^((~b3)& b4 ); - a23 = b3 ^((~b4)& b0 ); - a24 = b4 ^((~b0)& b1 ); - - b1 = ROL64((a30^d0), 36); - b2 = ROL64((a31^d1), 10); - b3 = ROL64((a32^d2), 15); - b4 = ROL64((a33^d3), 56); - b0 = ROL64((a34^d4), 27); - a30 = b0 ^((~b1)& b2 ); - a31 = b1 ^((~b2)& b3 ); - a32 = b2 ^((~b3)& b4 ); - a33 = b3 ^((~b4)& b0 ); - a34 = b4 ^((~b0)& b1 ); - - b3 = ROL64((a40^d0), 41); - b4 = ROL64((a41^d1), 2); - b0 = ROL64((a42^d2), 62); - b1 = ROL64((a43^d3), 55); - b2 = ROL64((a44^d4), 39); - a40 = b0 ^((~b1)& b2 ); - a41 = b1 ^((~b2)& b3 ); - a42 = b2 ^((~b3)& b4 ); - a43 = b3 ^((~b4)& b0 ); - a44 = b4 ^((~b0)& b1 ); - } + for(i=0; i<24; i+=4){ + c0 = a00^a10^a20^a30^a40; + c1 = a01^a11^a21^a31^a41; + c2 = a02^a12^a22^a32^a42; + c3 = a03^a13^a23^a33^a43; + c4 = a04^a14^a24^a34^a44; + d0 = c4^ROL64(c1, 1); + d1 = c0^ROL64(c2, 1); + d2 = c1^ROL64(c3, 1); + d3 = c2^ROL64(c4, 1); + d4 = c3^ROL64(c0, 1); + + b0 = (a00^d0); + b1 = ROL64((a11^d1), 44); + b2 = ROL64((a22^d2), 43); + b3 = ROL64((a33^d3), 21); + b4 = ROL64((a44^d4), 14); + a00 = b0 ^((~b1)& b2 ); + a00 ^= RC[i]; + a11 = b1 ^((~b2)& b3 ); + a22 = b2 ^((~b3)& b4 ); + a33 = b3 ^((~b4)& b0 ); + a44 = b4 ^((~b0)& b1 ); + + b2 = ROL64((a20^d0), 3); + b3 = ROL64((a31^d1), 45); + b4 = ROL64((a42^d2), 61); + b0 = ROL64((a03^d3), 28); + b1 = ROL64((a14^d4), 20); + a20 = b0 ^((~b1)& b2 ); + a31 = b1 ^((~b2)& b3 ); + a42 = b2 ^((~b3)& b4 ); + a03 = b3 ^((~b4)& b0 ); + a14 = b4 ^((~b0)& b1 ); + + b4 = ROL64((a40^d0), 18); + b0 = ROL64((a01^d1), 1); + b1 = ROL64((a12^d2), 6); + b2 = ROL64((a23^d3), 25); + b3 = ROL64((a34^d4), 8); + a40 = b0 ^((~b1)& b2 ); + a01 = b1 ^((~b2)& b3 ); + a12 = b2 ^((~b3)& b4 ); + a23 = b3 ^((~b4)& b0 ); + a34 = b4 ^((~b0)& b1 ); + + b1 = ROL64((a10^d0), 36); + b2 = ROL64((a21^d1), 10); + b3 = ROL64((a32^d2), 15); + b4 = ROL64((a43^d3), 56); + b0 = ROL64((a04^d4), 27); + a10 = b0 ^((~b1)& b2 ); + a21 = b1 ^((~b2)& b3 ); + a32 = b2 ^((~b3)& b4 ); + a43 = b3 ^((~b4)& b0 ); + a04 = b4 ^((~b0)& b1 ); + + b3 = ROL64((a30^d0), 41); + b4 = ROL64((a41^d1), 2); + b0 = ROL64((a02^d2), 62); + b1 = ROL64((a13^d3), 55); + b2 = ROL64((a24^d4), 39); + a30 = b0 ^((~b1)& b2 ); + a41 = b1 ^((~b2)& b3 ); + a02 = b2 ^((~b3)& b4 ); + a13 = b3 ^((~b4)& b0 ); + a24 = b4 ^((~b0)& b1 ); + + c0 = a00^a20^a40^a10^a30; + c1 = a11^a31^a01^a21^a41; + c2 = a22^a42^a12^a32^a02; + c3 = a33^a03^a23^a43^a13; + c4 = a44^a14^a34^a04^a24; + d0 = c4^ROL64(c1, 1); + d1 = c0^ROL64(c2, 1); + d2 = c1^ROL64(c3, 1); + d3 = c2^ROL64(c4, 1); + d4 = c3^ROL64(c0, 1); + + b0 = (a00^d0); + b1 = ROL64((a31^d1), 44); + b2 = ROL64((a12^d2), 43); + b3 = ROL64((a43^d3), 21); + b4 = ROL64((a24^d4), 14); + a00 = b0 ^((~b1)& b2 ); + a00 ^= RC[i+1]; + a31 = b1 ^((~b2)& b3 ); + a12 = b2 ^((~b3)& b4 ); + a43 = b3 ^((~b4)& b0 ); + a24 = b4 ^((~b0)& b1 ); + + b2 = ROL64((a40^d0), 3); + b3 = ROL64((a21^d1), 45); + b4 = ROL64((a02^d2), 61); + b0 = ROL64((a33^d3), 28); + b1 = ROL64((a14^d4), 20); + a40 = b0 ^((~b1)& b2 ); + a21 = b1 ^((~b2)& b3 ); + a02 = b2 ^((~b3)& b4 ); + a33 = b3 ^((~b4)& b0 ); + a14 = b4 ^((~b0)& b1 ); + + b4 = ROL64((a30^d0), 18); + b0 = ROL64((a11^d1), 1); + b1 = ROL64((a42^d2), 6); + b2 = ROL64((a23^d3), 25); + b3 = ROL64((a04^d4), 8); + a30 = b0 ^((~b1)& b2 ); + a11 = b1 ^((~b2)& b3 ); + a42 = b2 ^((~b3)& b4 ); + a23 = b3 ^((~b4)& b0 ); + a04 = b4 ^((~b0)& b1 ); + + b1 = ROL64((a20^d0), 36); + b2 = ROL64((a01^d1), 10); + b3 = ROL64((a32^d2), 15); + b4 = ROL64((a13^d3), 56); + b0 = ROL64((a44^d4), 27); + a20 = b0 ^((~b1)& b2 ); + a01 = b1 ^((~b2)& b3 ); + a32 = b2 ^((~b3)& b4 ); + a13 = b3 ^((~b4)& b0 ); + a44 = b4 ^((~b0)& b1 ); + + b3 = ROL64((a10^d0), 41); + b4 = ROL64((a41^d1), 2); + b0 = ROL64((a22^d2), 62); + b1 = ROL64((a03^d3), 55); + b2 = ROL64((a34^d4), 39); + a10 = b0 ^((~b1)& b2 ); + a41 = b1 ^((~b2)& b3 ); + a22 = b2 ^((~b3)& b4 ); + a03 = b3 ^((~b4)& b0 ); + a34 = b4 ^((~b0)& b1 ); + + c0 = a00^a40^a30^a20^a10; + c1 = a31^a21^a11^a01^a41; + c2 = a12^a02^a42^a32^a22; + c3 = a43^a33^a23^a13^a03; + c4 = a24^a14^a04^a44^a34; + d0 = c4^ROL64(c1, 1); + d1 = c0^ROL64(c2, 1); + d2 = c1^ROL64(c3, 1); + d3 = c2^ROL64(c4, 1); + d4 = c3^ROL64(c0, 1); + + b0 = (a00^d0); + b1 = ROL64((a21^d1), 44); + b2 = ROL64((a42^d2), 43); + b3 = ROL64((a13^d3), 21); + b4 = ROL64((a34^d4), 14); + a00 = b0 ^((~b1)& b2 ); + a00 ^= RC[i+2]; + a21 = b1 ^((~b2)& b3 ); + a42 = b2 ^((~b3)& b4 ); + a13 = b3 ^((~b4)& b0 ); + a34 = b4 ^((~b0)& b1 ); + + b2 = ROL64((a30^d0), 3); + b3 = ROL64((a01^d1), 45); + b4 = ROL64((a22^d2), 61); + b0 = ROL64((a43^d3), 28); + b1 = ROL64((a14^d4), 20); + a30 = b0 ^((~b1)& b2 ); + a01 = b1 ^((~b2)& b3 ); + a22 = b2 ^((~b3)& b4 ); + a43 = b3 ^((~b4)& b0 ); + a14 = b4 ^((~b0)& b1 ); + + b4 = ROL64((a10^d0), 18); + b0 = ROL64((a31^d1), 1); + b1 = ROL64((a02^d2), 6); + b2 = ROL64((a23^d3), 25); + b3 = ROL64((a44^d4), 8); + a10 = b0 ^((~b1)& b2 ); + a31 = b1 ^((~b2)& b3 ); + a02 = b2 ^((~b3)& b4 ); + a23 = b3 ^((~b4)& b0 ); + a44 = b4 ^((~b0)& b1 ); + + b1 = ROL64((a40^d0), 36); + b2 = ROL64((a11^d1), 10); + b3 = ROL64((a32^d2), 15); + b4 = ROL64((a03^d3), 56); + b0 = ROL64((a24^d4), 27); + a40 = b0 ^((~b1)& b2 ); + a11 = b1 ^((~b2)& b3 ); + a32 = b2 ^((~b3)& b4 ); + a03 = b3 ^((~b4)& b0 ); + a24 = b4 ^((~b0)& b1 ); + + b3 = ROL64((a20^d0), 41); + b4 = ROL64((a41^d1), 2); + b0 = ROL64((a12^d2), 62); + b1 = ROL64((a33^d3), 55); + b2 = ROL64((a04^d4), 39); + a20 = b0 ^((~b1)& b2 ); + a41 = b1 ^((~b2)& b3 ); + a12 = b2 ^((~b3)& b4 ); + a33 = b3 ^((~b4)& b0 ); + a04 = b4 ^((~b0)& b1 ); + + c0 = a00^a30^a10^a40^a20; + c1 = a21^a01^a31^a11^a41; + c2 = a42^a22^a02^a32^a12; + c3 = a13^a43^a23^a03^a33; + c4 = a34^a14^a44^a24^a04; + d0 = c4^ROL64(c1, 1); + d1 = c0^ROL64(c2, 1); + d2 = c1^ROL64(c3, 1); + d3 = c2^ROL64(c4, 1); + d4 = c3^ROL64(c0, 1); + + b0 = (a00^d0); + b1 = ROL64((a01^d1), 44); + b2 = ROL64((a02^d2), 43); + b3 = ROL64((a03^d3), 21); + b4 = ROL64((a04^d4), 14); + a00 = b0 ^((~b1)& b2 ); + a00 ^= RC[i+3]; + a01 = b1 ^((~b2)& b3 ); + a02 = b2 ^((~b3)& b4 ); + a03 = b3 ^((~b4)& b0 ); + a04 = b4 ^((~b0)& b1 ); + + b2 = ROL64((a10^d0), 3); + b3 = ROL64((a11^d1), 45); + b4 = ROL64((a12^d2), 61); + b0 = ROL64((a13^d3), 28); + b1 = ROL64((a14^d4), 20); + a10 = b0 ^((~b1)& b2 ); + a11 = b1 ^((~b2)& b3 ); + a12 = b2 ^((~b3)& b4 ); + a13 = b3 ^((~b4)& b0 ); + a14 = b4 ^((~b0)& b1 ); + + b4 = ROL64((a20^d0), 18); + b0 = ROL64((a21^d1), 1); + b1 = ROL64((a22^d2), 6); + b2 = ROL64((a23^d3), 25); + b3 = ROL64((a24^d4), 8); + a20 = b0 ^((~b1)& b2 ); + a21 = b1 ^((~b2)& b3 ); + a22 = b2 ^((~b3)& b4 ); + a23 = b3 ^((~b4)& b0 ); + a24 = b4 ^((~b0)& b1 ); + + b1 = ROL64((a30^d0), 36); + b2 = ROL64((a31^d1), 10); + b3 = ROL64((a32^d2), 15); + b4 = ROL64((a33^d3), 56); + b0 = ROL64((a34^d4), 27); + a30 = b0 ^((~b1)& b2 ); + a31 = b1 ^((~b2)& b3 ); + a32 = b2 ^((~b3)& b4 ); + a33 = b3 ^((~b4)& b0 ); + a34 = b4 ^((~b0)& b1 ); + + b3 = ROL64((a40^d0), 41); + b4 = ROL64((a41^d1), 2); + b0 = ROL64((a42^d2), 62); + b1 = ROL64((a43^d3), 55); + b2 = ROL64((a44^d4), 39); + a40 = b0 ^((~b1)& b2 ); + a41 = b1 ^((~b2)& b3 ); + a42 = b2 ^((~b3)& b4 ); + a43 = b3 ^((~b4)& b0 ); + a44 = b4 ^((~b0)& b1 ); + } } /* @@ -1827,27 +1827,27 @@ static void KeccakF1600Step(SHA3Context *p){ ** can be zero to use the default hash size of 256 bits. */ static void SHA3Init(SHA3Context *p, int iSize){ - memset(p, 0, sizeof(*p)); - if( iSize>=128 && iSize<=512 ){ - p->nRate = (1600 - ((iSize + 31)&~31)*2)/8; - }else{ - p->nRate = (1600 - 2*256)/8; - } + memset(p, 0, sizeof(*p)); + if( iSize>=128 && iSize<=512 ){ + p->nRate = (1600 - ((iSize + 31)&~31)*2)/8; + }else{ + p->nRate = (1600 - 2*256)/8; + } #if SHA3_BYTEORDER==1234 - /* Known to be little-endian at compile-time. No-op */ + /* Known to be little-endian at compile-time. No-op */ #elif SHA3_BYTEORDER==4321 - p->ixMask = 7; /* Big-endian */ + p->ixMask = 7; /* Big-endian */ #else - { - static unsigned int one = 1; - if( 1==*(unsigned char*)&one ){ - /* Little endian. No byte swapping. */ - p->ixMask = 0; - }else{ - /* Big endian. Byte swap. */ - p->ixMask = 7; - } + { + static unsigned int one = 1; + if( 1==*(unsigned char*)&one ){ + /* Little endian. No byte swapping. */ + p->ixMask = 0; + }else{ + /* Big endian. Byte swap. */ + p->ixMask = 7; } + } #endif } @@ -1856,37 +1856,37 @@ static void SHA3Init(SHA3Context *p, int iSize){ ** to the hash */ static void SHA3Update( - SHA3Context *p, - const unsigned char *aData, - unsigned int nData + SHA3Context *p, + const unsigned char *aData, + unsigned int nData ){ - unsigned int i = 0; + unsigned int i = 0; #if SHA3_BYTEORDER==1234 - if( (p->nLoaded % 8)==0 && ((aData - (const unsigned char*)0)&7)==0 ){ - for(; i+7u.s[p->nLoaded/8] ^= *(u64*)&aData[i]; - p->nLoaded += 8; - if( p->nLoaded>=p->nRate ){ - KeccakF1600Step(p); - p->nLoaded = 0; - } - } - } + if( (p->nLoaded % 8)==0 && ((aData - (const unsigned char*)0)&7)==0 ){ + for(; i+7u.s[p->nLoaded/8] ^= *(u64*)&aData[i]; + p->nLoaded += 8; + if( p->nLoaded>=p->nRate ){ + KeccakF1600Step(p); + p->nLoaded = 0; + } + } + } #endif - for(; iu.x[p->nLoaded] ^= aData[i]; + p->u.x[p->nLoaded] ^= aData[i]; #elif SHA3_BYTEORDER==4321 - p->u.x[p->nLoaded^0x07] ^= aData[i]; + p->u.x[p->nLoaded^0x07] ^= aData[i]; #else - p->u.x[p->nLoaded^p->ixMask] ^= aData[i]; + p->u.x[p->nLoaded^p->ixMask] ^= aData[i]; #endif - p->nLoaded++; - if( p->nLoaded==p->nRate ){ - KeccakF1600Step(p); - p->nLoaded = 0; - } + p->nLoaded++; + if( p->nLoaded==p->nRate ){ + KeccakF1600Step(p); + p->nLoaded = 0; } + } } /* @@ -1895,21 +1895,21 @@ static void SHA3Update( ** hash value. */ static unsigned char *SHA3Final(SHA3Context *p){ - unsigned int i; - if( p->nLoaded==p->nRate-1 ){ - const unsigned char c1 = 0x86; - SHA3Update(p, &c1, 1); - }else{ - const unsigned char c2 = 0x06; - const unsigned char c3 = 0x80; - SHA3Update(p, &c2, 1); - p->nLoaded = p->nRate - 1; - SHA3Update(p, &c3, 1); - } - for(i=0; inRate; i++){ - p->u.x[i+p->nRate] = p->u.x[i^p->ixMask]; - } - return &p->u.x[p->nRate]; + unsigned int i; + if( p->nLoaded==p->nRate-1 ){ + const unsigned char c1 = 0x86; + SHA3Update(p, &c1, 1); + }else{ + const unsigned char c2 = 0x06; + const unsigned char c3 = 0x80; + SHA3Update(p, &c2, 1); + p->nLoaded = p->nRate - 1; + SHA3Update(p, &c3, 1); + } + for(i=0; inRate; i++){ + p->u.x[i+p->nRate] = p->u.x[i^p->ixMask]; + } + return &p->u.x[p->nRate]; } /* End of the hashing logic *****************************************************************************/ @@ -1918,56 +1918,56 @@ static unsigned char *SHA3Final(SHA3Context *p){ ** Implementation of the sha3(X,SIZE) function. ** ** Return a BLOB which is the SIZE-bit SHA3 hash of X. The default -** size is 256. If X is a BLOB, it is hashed as is. +** size is 256. If X is a BLOB, it is hashed as is. ** For all other non-NULL types of input, X is converted into a UTF-8 string ** and the string is hashed without the trailing 0x00 terminator. The hash ** of a NULL value is NULL. */ static void sha3Func( - sqlite3_context *context, - int argc, - sqlite3_value **argv + sqlite3_context *context, + int argc, + sqlite3_value **argv ){ - SHA3Context cx; - int eType = sqlite3_value_type(argv[0]); - int nByte = sqlite3_value_bytes(argv[0]); - int iSize; - if( argc==1 ){ - iSize = 256; - }else{ - iSize = sqlite3_value_int(argv[1]); - if( iSize!=224 && iSize!=256 && iSize!=384 && iSize!=512 ){ - sqlite3_result_error(context, "SHA3 size should be one of: 224 256 " - "384 512", -1); - return; - } - } - if( eType==SQLITE_NULL ) return; - SHA3Init(&cx, iSize); - if( eType==SQLITE_BLOB ){ - SHA3Update(&cx, sqlite3_value_blob(argv[0]), nByte); - }else{ - SHA3Update(&cx, sqlite3_value_text(argv[0]), nByte); - } - sqlite3_result_blob(context, SHA3Final(&cx), iSize/8, SQLITE_TRANSIENT); + SHA3Context cx; + int eType = sqlite3_value_type(argv[0]); + int nByte = sqlite3_value_bytes(argv[0]); + int iSize; + if( argc==1 ){ + iSize = 256; + }else{ + iSize = sqlite3_value_int(argv[1]); + if( iSize!=224 && iSize!=256 && iSize!=384 && iSize!=512 ){ + sqlite3_result_error(context, "SHA3 size should be one of: 224 256 " + "384 512", -1); + return; + } + } + if( eType==SQLITE_NULL ) return; + SHA3Init(&cx, iSize); + if( eType==SQLITE_BLOB ){ + SHA3Update(&cx, sqlite3_value_blob(argv[0]), nByte); + }else{ + SHA3Update(&cx, sqlite3_value_text(argv[0]), nByte); + } + sqlite3_result_blob(context, SHA3Final(&cx), iSize/8, SQLITE_TRANSIENT); } /* Compute a string using sqlite3_vsnprintf() with a maximum length ** of 50 bytes and add it to the hash. */ static void hash_step_vformat( - SHA3Context *p, /* Add content to this context */ - const char *zFormat, - ... + SHA3Context *p, /* Add content to this context */ + const char *zFormat, + ... ){ - va_list ap; - int n; - char zBuf[50]; - va_start(ap, zFormat); - sqlite3_vsnprintf(sizeof(zBuf),zBuf,zFormat,ap); - va_end(ap); - n = (int)strlen(zBuf); - SHA3Update(p, (unsigned char*)zBuf, n); + va_list ap; + int n; + char zBuf[50]; + va_start(ap, zFormat); + sqlite3_vsnprintf(sizeof(zBuf),zBuf,zFormat,ap); + va_end(ap); + n = (int)strlen(zBuf); + SHA3Update(p, (unsigned char*)zBuf, n); } /* @@ -2003,115 +2003,115 @@ static void hash_step_vformat( ** with no delimiters of any kind. */ static void sha3QueryFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv + sqlite3_context *context, + int argc, + sqlite3_value **argv ){ - sqlite3 *db = sqlite3_context_db_handle(context); - const char *zSql = (const char*)sqlite3_value_text(argv[0]); - sqlite3_stmt *pStmt = 0; - int nCol; /* Number of columns in the result set */ - int i; /* Loop counter */ - int rc; - int n; - const char *z; - SHA3Context cx; - int iSize; - - if( argc==1 ){ - iSize = 256; - }else{ - iSize = sqlite3_value_int(argv[1]); - if( iSize!=224 && iSize!=256 && iSize!=384 && iSize!=512 ){ - sqlite3_result_error(context, "SHA3 size should be one of: 224 256 " - "384 512", -1); - return; - } - } - if( zSql==0 ) return; - SHA3Init(&cx, iSize); - while( zSql[0] ){ - rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, &zSql); - if( rc ){ - char *zMsg = sqlite3_mprintf("error SQL statement [%s]: %s", - zSql, sqlite3_errmsg(db)); - sqlite3_finalize(pStmt); - sqlite3_result_error(context, zMsg, -1); - sqlite3_free(zMsg); - return; - } - if( !sqlite3_stmt_readonly(pStmt) ){ - char *zMsg = sqlite3_mprintf("non-query: [%s]", sqlite3_sql(pStmt)); - sqlite3_finalize(pStmt); - sqlite3_result_error(context, zMsg, -1); - sqlite3_free(zMsg); - return; - } - nCol = sqlite3_column_count(pStmt); - z = sqlite3_sql(pStmt); - if( z ){ - n = (int)strlen(z); - hash_step_vformat(&cx,"S%d:",n); - SHA3Update(&cx,(unsigned char*)z,n); - } - - /* Compute a hash over the result of the query */ - while( SQLITE_ROW==sqlite3_step(pStmt) ){ - SHA3Update(&cx,(const unsigned char*)"R",1); - for(i=0; i=1; j--){ - x[j] = u & 0xff; - u >>= 8; - } - x[0] = 'I'; - SHA3Update(&cx, x, 9); - break; - } - case SQLITE_FLOAT: { - sqlite3_uint64 u; - int j; - unsigned char x[9]; - double r = sqlite3_column_double(pStmt,i); - memcpy(&u, &r, 8); - for(j=8; j>=1; j--){ - x[j] = u & 0xff; - u >>= 8; - } - x[0] = 'F'; - SHA3Update(&cx,x,9); - break; - } - case SQLITE_TEXT: { - int n2 = sqlite3_column_bytes(pStmt, i); - const unsigned char *z2 = sqlite3_column_text(pStmt, i); - hash_step_vformat(&cx,"T%d:",n2); - SHA3Update(&cx, z2, n2); - break; - } - case SQLITE_BLOB: { - int n2 = sqlite3_column_bytes(pStmt, i); - const unsigned char *z2 = sqlite3_column_blob(pStmt, i); - hash_step_vformat(&cx,"B%d:",n2); - SHA3Update(&cx, z2, n2); - break; - } - } - } + sqlite3 *db = sqlite3_context_db_handle(context); + const char *zSql = (const char*)sqlite3_value_text(argv[0]); + sqlite3_stmt *pStmt = 0; + int nCol; /* Number of columns in the result set */ + int i; /* Loop counter */ + int rc; + int n; + const char *z; + SHA3Context cx; + int iSize; + + if( argc==1 ){ + iSize = 256; + }else{ + iSize = sqlite3_value_int(argv[1]); + if( iSize!=224 && iSize!=256 && iSize!=384 && iSize!=512 ){ + sqlite3_result_error(context, "SHA3 size should be one of: 224 256 " + "384 512", -1); + return; + } + } + if( zSql==0 ) return; + SHA3Init(&cx, iSize); + while( zSql[0] ){ + rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, &zSql); + if( rc ){ + char *zMsg = sqlite3_mprintf("error SQL statement [%s]: %s", + zSql, sqlite3_errmsg(db)); + sqlite3_finalize(pStmt); + sqlite3_result_error(context, zMsg, -1); + sqlite3_free(zMsg); + return; + } + if( !sqlite3_stmt_readonly(pStmt) ){ + char *zMsg = sqlite3_mprintf("non-query: [%s]", sqlite3_sql(pStmt)); + sqlite3_finalize(pStmt); + sqlite3_result_error(context, zMsg, -1); + sqlite3_free(zMsg); + return; + } + nCol = sqlite3_column_count(pStmt); + z = sqlite3_sql(pStmt); + if( z ){ + n = (int)strlen(z); + hash_step_vformat(&cx,"S%d:",n); + SHA3Update(&cx,(unsigned char*)z,n); + } + + /* Compute a hash over the result of the query */ + while( SQLITE_ROW==sqlite3_step(pStmt) ){ + SHA3Update(&cx,(const unsigned char*)"R",1); + for(i=0; i=1; j--){ + x[j] = u & 0xff; + u >>= 8; + } + x[0] = 'I'; + SHA3Update(&cx, x, 9); + break; + } + case SQLITE_FLOAT: { + sqlite3_uint64 u; + int j; + unsigned char x[9]; + double r = sqlite3_column_double(pStmt,i); + memcpy(&u, &r, 8); + for(j=8; j>=1; j--){ + x[j] = u & 0xff; + u >>= 8; + } + x[0] = 'F'; + SHA3Update(&cx,x,9); + break; + } + case SQLITE_TEXT: { + int n2 = sqlite3_column_bytes(pStmt, i); + const unsigned char *z2 = sqlite3_column_text(pStmt, i); + hash_step_vformat(&cx,"T%d:",n2); + SHA3Update(&cx, z2, n2); + break; + } + case SQLITE_BLOB: { + int n2 = sqlite3_column_bytes(pStmt, i); + const unsigned char *z2 = sqlite3_column_blob(pStmt, i); + hash_step_vformat(&cx,"B%d:",n2); + SHA3Update(&cx, z2, n2); + break; + } } - sqlite3_finalize(pStmt); + } } - sqlite3_result_blob(context, SHA3Final(&cx), iSize/8, SQLITE_TRANSIENT); + sqlite3_finalize(pStmt); + } + sqlite3_result_blob(context, SHA3Final(&cx), iSize/8, SQLITE_TRANSIENT); } @@ -2119,32 +2119,32 @@ static void sha3QueryFunc( #endif int sqlite3_shathree_init( - sqlite3 *db, - char **pzErrMsg, - const sqlite3_api_routines *pApi + sqlite3 *db, + char **pzErrMsg, + const sqlite3_api_routines *pApi ){ - int rc = SQLITE_OK; - SQLITE_EXTENSION_INIT2(pApi); - (void)pzErrMsg; /* Unused parameter */ - rc = sqlite3_create_function(db, "sha3", 1, - SQLITE_UTF8 | SQLITE_INNOCUOUS | SQLITE_DETERMINISTIC, - 0, sha3Func, 0, 0); - if( rc==SQLITE_OK ){ - rc = sqlite3_create_function(db, "sha3", 2, - SQLITE_UTF8 | SQLITE_INNOCUOUS | SQLITE_DETERMINISTIC, - 0, sha3Func, 0, 0); - } - if( rc==SQLITE_OK ){ - rc = sqlite3_create_function(db, "sha3_query", 1, - SQLITE_UTF8 | SQLITE_DIRECTONLY, - 0, sha3QueryFunc, 0, 0); - } - if( rc==SQLITE_OK ){ - rc = sqlite3_create_function(db, "sha3_query", 2, - SQLITE_UTF8 | SQLITE_DIRECTONLY, - 0, sha3QueryFunc, 0, 0); - } - return rc; + int rc = SQLITE_OK; + SQLITE_EXTENSION_INIT2(pApi); + (void)pzErrMsg; /* Unused parameter */ + rc = sqlite3_create_function(db, "sha3", 1, + SQLITE_UTF8 | SQLITE_INNOCUOUS | SQLITE_DETERMINISTIC, + 0, sha3Func, 0, 0); + if( rc==SQLITE_OK ){ + rc = sqlite3_create_function(db, "sha3", 2, + SQLITE_UTF8 | SQLITE_INNOCUOUS | SQLITE_DETERMINISTIC, + 0, sha3Func, 0, 0); + } + if( rc==SQLITE_OK ){ + rc = sqlite3_create_function(db, "sha3_query", 1, + SQLITE_UTF8 | SQLITE_DIRECTONLY, + 0, sha3QueryFunc, 0, 0); + } + if( rc==SQLITE_OK ){ + rc = sqlite3_create_function(db, "sha3_query", 2, + SQLITE_UTF8 | SQLITE_DIRECTONLY, + 0, sha3QueryFunc, 0, 0); + } + return rc; } /************************* End ../ext/misc/shathree.c ********************/ @@ -2220,8 +2220,8 @@ int sqlite3_shathree_init( ** directory, NULL. ** ** If a non-NULL value is specified for the optional $dir parameter and -** $path is a relative path, then $path is interpreted relative to $dir. -** And the paths returned in the "name" column of the table are also +** $path is a relative path, then $path is interpreted relative to $dir. +** And the paths returned in the "name" column of the table are also ** relative to directory $dir. ** ** Notes on building this extension for Windows: @@ -2265,7 +2265,7 @@ SQLITE_EXTENSION_INIT1 /* ** Structure of the fsdir() table-valued function */ -/* 0 1 2 3 4 5 */ + /* 0 1 2 3 4 5 */ #define FSDIR_SCHEMA "(name,mode,mtime,data,path HIDDEN,dir HIDDEN)" #define FSDIR_COLUMN_NAME 0 /* Name of the file */ #define FSDIR_COLUMN_MODE 1 /* Access mode */ @@ -2276,7 +2276,7 @@ SQLITE_EXTENSION_INIT1 /* -** Set the result stored by context ctx to a blob containing the +** Set the result stored by context ctx to a blob containing the ** contents of file zName. Or, leave the result unchanged (NULL) ** if the file does not exist or is unreadable. ** @@ -2287,40 +2287,40 @@ SQLITE_EXTENSION_INIT1 ** off of disk. */ static void readFileContents(sqlite3_context *ctx, const char *zName){ - FILE *in; - sqlite3_int64 nIn; - void *pBuf; - sqlite3 *db; - int mxBlob; - - in = fopen(zName, "rb"); - if( in==0 ){ - /* File does not exist or is unreadable. Leave the result set to NULL. */ - return; - } - fseek(in, 0, SEEK_END); - nIn = ftell(in); - rewind(in); - db = sqlite3_context_db_handle(ctx); - mxBlob = sqlite3_limit(db, SQLITE_LIMIT_LENGTH, -1); - if( nIn>mxBlob ){ - sqlite3_result_error_code(ctx, SQLITE_TOOBIG); - fclose(in); - return; - } - pBuf = sqlite3_malloc64( nIn ? nIn : 1 ); - if( pBuf==0 ){ - sqlite3_result_error_nomem(ctx); - fclose(in); - return; - } - if( nIn==(sqlite3_int64)fread(pBuf, 1, (size_t)nIn, in) ){ - sqlite3_result_blob64(ctx, pBuf, nIn, sqlite3_free); - }else{ - sqlite3_result_error_code(ctx, SQLITE_IOERR); - sqlite3_free(pBuf); - } + FILE *in; + sqlite3_int64 nIn; + void *pBuf; + sqlite3 *db; + int mxBlob; + + in = fopen(zName, "rb"); + if( in==0 ){ + /* File does not exist or is unreadable. Leave the result set to NULL. */ + return; + } + fseek(in, 0, SEEK_END); + nIn = ftell(in); + rewind(in); + db = sqlite3_context_db_handle(ctx); + mxBlob = sqlite3_limit(db, SQLITE_LIMIT_LENGTH, -1); + if( nIn>mxBlob ){ + sqlite3_result_error_code(ctx, SQLITE_TOOBIG); fclose(in); + return; + } + pBuf = sqlite3_malloc64( nIn ? nIn : 1 ); + if( pBuf==0 ){ + sqlite3_result_error_nomem(ctx); + fclose(in); + return; + } + if( nIn==(sqlite3_int64)fread(pBuf, 1, (size_t)nIn, in) ){ + sqlite3_result_blob64(ctx, pBuf, nIn, sqlite3_free); + }else{ + sqlite3_result_error_code(ctx, SQLITE_IOERR); + sqlite3_free(pBuf); + } + fclose(in); } /* @@ -2329,15 +2329,15 @@ static void readFileContents(sqlite3_context *ctx, const char *zName){ ** if the file does not exist or is unreadable. */ static void readfileFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv + sqlite3_context *context, + int argc, + sqlite3_value **argv ){ - const char *zName; - (void)(argc); /* Unused parameter */ - zName = (const char*)sqlite3_value_text(argv[0]); - if( zName==0 ) return; - readFileContents(context, zName); + const char *zName; + (void)(argc); /* Unused parameter */ + zName = (const char*)sqlite3_value_text(argv[0]); + if( zName==0 ) return; + readFileContents(context, zName); } /* @@ -2345,13 +2345,13 @@ static void readfileFunc( ** vprintf(zFmt, ...). */ static void ctxErrorMsg(sqlite3_context *ctx, const char *zFmt, ...){ - char *zMsg = 0; - va_list ap; - va_start(ap, zFmt); - zMsg = sqlite3_vmprintf(zFmt, ap); - sqlite3_result_error(ctx, zMsg, -1); - sqlite3_free(zMsg); - va_end(ap); + char *zMsg = 0; + va_list ap; + va_start(ap, zFmt); + zMsg = sqlite3_vmprintf(zFmt, ap); + sqlite3_result_error(ctx, zMsg, -1); + sqlite3_free(zMsg); + va_end(ap); } #if defined(_WIN32) @@ -2360,25 +2360,25 @@ static void ctxErrorMsg(sqlite3_context *ctx, const char *zFmt, ...){ ** number of seconds since the Unix Epoch (1970-01-01 00:00:00 UTC). */ static sqlite3_uint64 fileTimeToUnixTime( - LPFILETIME pFileTime + LPFILETIME pFileTime ){ - SYSTEMTIME epochSystemTime; - ULARGE_INTEGER epochIntervals; - FILETIME epochFileTime; - ULARGE_INTEGER fileIntervals; + SYSTEMTIME epochSystemTime; + ULARGE_INTEGER epochIntervals; + FILETIME epochFileTime; + ULARGE_INTEGER fileIntervals; - memset(&epochSystemTime, 0, sizeof(SYSTEMTIME)); - epochSystemTime.wYear = 1970; - epochSystemTime.wMonth = 1; - epochSystemTime.wDay = 1; - SystemTimeToFileTime(&epochSystemTime, &epochFileTime); - epochIntervals.LowPart = epochFileTime.dwLowDateTime; - epochIntervals.HighPart = epochFileTime.dwHighDateTime; + memset(&epochSystemTime, 0, sizeof(SYSTEMTIME)); + epochSystemTime.wYear = 1970; + epochSystemTime.wMonth = 1; + epochSystemTime.wDay = 1; + SystemTimeToFileTime(&epochSystemTime, &epochFileTime); + epochIntervals.LowPart = epochFileTime.dwLowDateTime; + epochIntervals.HighPart = epochFileTime.dwHighDateTime; - fileIntervals.LowPart = pFileTime->dwLowDateTime; - fileIntervals.HighPart = pFileTime->dwHighDateTime; + fileIntervals.LowPart = pFileTime->dwLowDateTime; + fileIntervals.HighPart = pFileTime->dwHighDateTime; - return (fileIntervals.QuadPart - epochIntervals.QuadPart) / 10000000; + return (fileIntervals.QuadPart - epochIntervals.QuadPart) / 10000000; } @@ -2388,12 +2388,12 @@ static sqlite3_uint64 fileTimeToUnixTime( # define sqlite3_win32_utf8_to_unicode utf8_to_utf16 # LPWSTR utf8_to_utf16(const char *z){ - int nAllot = MultiByteToWideChar(CP_UTF8, 0, z, -1, NULL, 0); - LPWSTR rv = sqlite3_malloc(nAllot * sizeof(WCHAR)); - if( rv!=0 && 0 < MultiByteToWideChar(CP_UTF8, 0, z, -1, rv, nAllot) ) - return rv; - sqlite3_free(rv); - return 0; + int nAllot = MultiByteToWideChar(CP_UTF8, 0, z, -1, NULL, 0); + LPWSTR rv = sqlite3_malloc(nAllot * sizeof(WCHAR)); + if( rv!=0 && 0 < MultiByteToWideChar(CP_UTF8, 0, z, -1, rv, nAllot) ) + return rv; + sqlite3_free(rv); + return 0; } #endif @@ -2403,25 +2403,25 @@ LPWSTR utf8_to_utf16(const char *z){ ** appears to return these values as local times. */ static void statTimesToUtc( - const char *zPath, - struct stat *pStatBuf + const char *zPath, + struct stat *pStatBuf ){ - HANDLE hFindFile; - WIN32_FIND_DATAW fd; - LPWSTR zUnicodeName; - extern LPWSTR sqlite3_win32_utf8_to_unicode(const char*); - zUnicodeName = sqlite3_win32_utf8_to_unicode(zPath); - if( zUnicodeName ){ - memset(&fd, 0, sizeof(WIN32_FIND_DATAW)); - hFindFile = FindFirstFileW(zUnicodeName, &fd); - if( hFindFile!=NULL ){ - pStatBuf->st_ctime = (time_t)fileTimeToUnixTime(&fd.ftCreationTime); - pStatBuf->st_atime = (time_t)fileTimeToUnixTime(&fd.ftLastAccessTime); - pStatBuf->st_mtime = (time_t)fileTimeToUnixTime(&fd.ftLastWriteTime); - FindClose(hFindFile); - } - sqlite3_free(zUnicodeName); - } + HANDLE hFindFile; + WIN32_FIND_DATAW fd; + LPWSTR zUnicodeName; + extern LPWSTR sqlite3_win32_utf8_to_unicode(const char*); + zUnicodeName = sqlite3_win32_utf8_to_unicode(zPath); + if( zUnicodeName ){ + memset(&fd, 0, sizeof(WIN32_FIND_DATAW)); + hFindFile = FindFirstFileW(zUnicodeName, &fd); + if( hFindFile!=NULL ){ + pStatBuf->st_ctime = (time_t)fileTimeToUnixTime(&fd.ftCreationTime); + pStatBuf->st_atime = (time_t)fileTimeToUnixTime(&fd.ftLastAccessTime); + pStatBuf->st_mtime = (time_t)fileTimeToUnixTime(&fd.ftLastWriteTime); + FindClose(hFindFile); + } + sqlite3_free(zUnicodeName); + } } #endif @@ -2431,15 +2431,15 @@ static void statTimesToUtc( ** other systems, this function simply calls stat(). */ static int fileStat( - const char *zPath, - struct stat *pStatBuf + const char *zPath, + struct stat *pStatBuf ){ #if defined(_WIN32) - int rc = stat(zPath, pStatBuf); - if( rc==0 ) statTimesToUtc(zPath, pStatBuf); - return rc; + int rc = stat(zPath, pStatBuf); + if( rc==0 ) statTimesToUtc(zPath, pStatBuf); + return rc; #else - return stat(zPath, pStatBuf); + return stat(zPath, pStatBuf); #endif } @@ -2449,15 +2449,15 @@ static int fileStat( ** other systems, this function simply calls lstat(). */ static int fileLinkStat( - const char *zPath, - struct stat *pStatBuf + const char *zPath, + struct stat *pStatBuf ){ #if defined(_WIN32) - int rc = lstat(zPath, pStatBuf); - if( rc==0 ) statTimesToUtc(zPath, pStatBuf); - return rc; + int rc = lstat(zPath, pStatBuf); + if( rc==0 ) statTimesToUtc(zPath, pStatBuf); + return rc; #else - return lstat(zPath, pStatBuf); + return lstat(zPath, pStatBuf); #endif } @@ -2473,201 +2473,201 @@ static int fileLinkStat( ** SQLITE_ERROR otherwise. */ static int makeDirectory( - const char *zFile + const char *zFile ){ - char *zCopy = sqlite3_mprintf("%s", zFile); - int rc = SQLITE_OK; + char *zCopy = sqlite3_mprintf("%s", zFile); + int rc = SQLITE_OK; - if( zCopy==0 ){ - rc = SQLITE_NOMEM; - }else{ - int nCopy = (int)strlen(zCopy); - int i = 1; + if( zCopy==0 ){ + rc = SQLITE_NOMEM; + }else{ + int nCopy = (int)strlen(zCopy); + int i = 1; - while( rc==SQLITE_OK ){ - struct stat sStat; - int rc2; + while( rc==SQLITE_OK ){ + struct stat sStat; + int rc2; - for(; zCopy[i]!='/' && i=0 ){ + } + }else{ + sqlite3_int64 nWrite = 0; + const char *z; + int rc = 0; + FILE *out = fopen(zFile, "wb"); + if( out==0 ) return 1; + z = (const char*)sqlite3_value_blob(pData); + if( z ){ + sqlite3_int64 n = fwrite(z, 1, sqlite3_value_bytes(pData), out); + nWrite = sqlite3_value_bytes(pData); + if( nWrite!=n ){ + rc = 1; + } + } + fclose(out); + if( rc==0 && mode && chmod(zFile, mode & 0777) ){ + rc = 1; + } + if( rc ) return 2; + sqlite3_result_int64(pCtx, nWrite); + } + } + + if( mtime>=0 ){ #if defined(_WIN32) #if !SQLITE_OS_WINRT - /* Windows */ - FILETIME lastAccess; - FILETIME lastWrite; - SYSTEMTIME currentTime; - LONGLONG intervals; - HANDLE hFile; - LPWSTR zUnicodeName; - extern LPWSTR sqlite3_win32_utf8_to_unicode(const char*); - - GetSystemTime(¤tTime); - SystemTimeToFileTime(¤tTime, &lastAccess); - intervals = Int32x32To64(mtime, 10000000) + 116444736000000000; - lastWrite.dwLowDateTime = (DWORD)intervals; - lastWrite.dwHighDateTime = intervals >> 32; - zUnicodeName = sqlite3_win32_utf8_to_unicode(zFile); - if( zUnicodeName==0 ){ - return 1; - } - hFile = CreateFileW( - zUnicodeName, FILE_WRITE_ATTRIBUTES, 0, NULL, OPEN_EXISTING, - FILE_FLAG_BACKUP_SEMANTICS, NULL - ); - sqlite3_free(zUnicodeName); - if( hFile!=INVALID_HANDLE_VALUE ){ - BOOL bResult = SetFileTime(hFile, NULL, &lastAccess, &lastWrite); - CloseHandle(hFile); - return !bResult; - }else{ - return 1; - } + /* Windows */ + FILETIME lastAccess; + FILETIME lastWrite; + SYSTEMTIME currentTime; + LONGLONG intervals; + HANDLE hFile; + LPWSTR zUnicodeName; + extern LPWSTR sqlite3_win32_utf8_to_unicode(const char*); + + GetSystemTime(¤tTime); + SystemTimeToFileTime(¤tTime, &lastAccess); + intervals = Int32x32To64(mtime, 10000000) + 116444736000000000; + lastWrite.dwLowDateTime = (DWORD)intervals; + lastWrite.dwHighDateTime = intervals >> 32; + zUnicodeName = sqlite3_win32_utf8_to_unicode(zFile); + if( zUnicodeName==0 ){ + return 1; + } + hFile = CreateFileW( + zUnicodeName, FILE_WRITE_ATTRIBUTES, 0, NULL, OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS, NULL + ); + sqlite3_free(zUnicodeName); + if( hFile!=INVALID_HANDLE_VALUE ){ + BOOL bResult = SetFileTime(hFile, NULL, &lastAccess, &lastWrite); + CloseHandle(hFile); + return !bResult; + }else{ + return 1; + } #endif #elif defined(AT_FDCWD) && 0 /* utimensat() is not universally available */ - /* Recent unix */ - struct timespec times[2]; - times[0].tv_nsec = times[1].tv_nsec = 0; - times[0].tv_sec = time(0); - times[1].tv_sec = mtime; - if( utimensat(AT_FDCWD, zFile, times, AT_SYMLINK_NOFOLLOW) ){ - return 1; - } + /* Recent unix */ + struct timespec times[2]; + times[0].tv_nsec = times[1].tv_nsec = 0; + times[0].tv_sec = time(0); + times[1].tv_sec = mtime; + if( utimensat(AT_FDCWD, zFile, times, AT_SYMLINK_NOFOLLOW) ){ + return 1; + } #else - /* Legacy unix */ - struct timeval times[2]; - times[0].tv_usec = times[1].tv_usec = 0; - times[0].tv_sec = time(0); - times[1].tv_sec = mtime; - if( utimes(zFile, times) ){ - return 1; - } -#endif + /* Legacy unix */ + struct timeval times[2]; + times[0].tv_usec = times[1].tv_usec = 0; + times[0].tv_sec = time(0); + times[1].tv_sec = mtime; + if( utimes(zFile, times) ){ + return 1; } +#endif + } - return 0; + return 0; } /* -** Implementation of the "writefile(W,X[,Y[,Z]]])" SQL function. +** Implementation of the "writefile(W,X[,Y[,Z]]])" SQL function. ** Refer to header comments at the top of this file for details. */ static void writefileFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv + sqlite3_context *context, + int argc, + sqlite3_value **argv ){ - const char *zFile; - mode_t mode = 0; - int res; - sqlite3_int64 mtime = -1; - - if( argc<2 || argc>4 ){ - sqlite3_result_error(context, - "wrong number of arguments to function writefile()", -1 - ); - return; - } - - zFile = (const char*)sqlite3_value_text(argv[0]); - if( zFile==0 ) return; - if( argc>=3 ){ - mode = (mode_t)sqlite3_value_int(argv[2]); - } - if( argc==4 ){ - mtime = sqlite3_value_int64(argv[3]); - } - - res = writeFile(context, zFile, argv[1], mode, mtime); - if( res==1 && errno==ENOENT ){ - if( makeDirectory(zFile)==SQLITE_OK ){ - res = writeFile(context, zFile, argv[1], mode, mtime); - } - } - - if( argc>2 && res!=0 ){ - if( S_ISLNK(mode) ){ - ctxErrorMsg(context, "failed to create symlink: %s", zFile); - }else if( S_ISDIR(mode) ){ - ctxErrorMsg(context, "failed to create directory: %s", zFile); - }else{ - ctxErrorMsg(context, "failed to write file: %s", zFile); - } + const char *zFile; + mode_t mode = 0; + int res; + sqlite3_int64 mtime = -1; + + if( argc<2 || argc>4 ){ + sqlite3_result_error(context, + "wrong number of arguments to function writefile()", -1 + ); + return; + } + + zFile = (const char*)sqlite3_value_text(argv[0]); + if( zFile==0 ) return; + if( argc>=3 ){ + mode = (mode_t)sqlite3_value_int(argv[2]); + } + if( argc==4 ){ + mtime = sqlite3_value_int64(argv[3]); + } + + res = writeFile(context, zFile, argv[1], mode, mtime); + if( res==1 && errno==ENOENT ){ + if( makeDirectory(zFile)==SQLITE_OK ){ + res = writeFile(context, zFile, argv[1], mode, mtime); + } + } + + if( argc>2 && res!=0 ){ + if( S_ISLNK(mode) ){ + ctxErrorMsg(context, "failed to create symlink: %s", zFile); + }else if( S_ISDIR(mode) ){ + ctxErrorMsg(context, "failed to create directory: %s", zFile); + }else{ + ctxErrorMsg(context, "failed to write file: %s", zFile); } + } } /* @@ -2677,114 +2677,114 @@ static void writefileFunc( ** text string in the style of "ls -l". */ static void lsModeFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv + sqlite3_context *context, + int argc, + sqlite3_value **argv ){ - int i; - int iMode = sqlite3_value_int(argv[0]); - char z[16]; - (void)argc; - if( S_ISLNK(iMode) ){ - z[0] = 'l'; - }else if( S_ISREG(iMode) ){ - z[0] = '-'; - }else if( S_ISDIR(iMode) ){ - z[0] = 'd'; - }else{ - z[0] = '?'; - } - for(i=0; i<3; i++){ - int m = (iMode >> ((2-i)*3)); - char *a = &z[1 + i*3]; - a[0] = (m & 0x4) ? 'r' : '-'; - a[1] = (m & 0x2) ? 'w' : '-'; - a[2] = (m & 0x1) ? 'x' : '-'; - } - z[10] = '\0'; - sqlite3_result_text(context, z, -1, SQLITE_TRANSIENT); + int i; + int iMode = sqlite3_value_int(argv[0]); + char z[16]; + (void)argc; + if( S_ISLNK(iMode) ){ + z[0] = 'l'; + }else if( S_ISREG(iMode) ){ + z[0] = '-'; + }else if( S_ISDIR(iMode) ){ + z[0] = 'd'; + }else{ + z[0] = '?'; + } + for(i=0; i<3; i++){ + int m = (iMode >> ((2-i)*3)); + char *a = &z[1 + i*3]; + a[0] = (m & 0x4) ? 'r' : '-'; + a[1] = (m & 0x2) ? 'w' : '-'; + a[2] = (m & 0x1) ? 'x' : '-'; + } + z[10] = '\0'; + sqlite3_result_text(context, z, -1, SQLITE_TRANSIENT); } #ifndef SQLITE_OMIT_VIRTUALTABLE -/* +/* ** Cursor type for recursively iterating through a directory structure. */ typedef struct fsdir_cursor fsdir_cursor; typedef struct FsdirLevel FsdirLevel; struct FsdirLevel { - DIR *pDir; /* From opendir() */ - char *zDir; /* Name of directory (nul-terminated) */ + DIR *pDir; /* From opendir() */ + char *zDir; /* Name of directory (nul-terminated) */ }; struct fsdir_cursor { - sqlite3_vtab_cursor base; /* Base class - must be first */ + sqlite3_vtab_cursor base; /* Base class - must be first */ - int nLvl; /* Number of entries in aLvl[] array */ - int iLvl; /* Index of current entry */ - FsdirLevel *aLvl; /* Hierarchy of directories being traversed */ + int nLvl; /* Number of entries in aLvl[] array */ + int iLvl; /* Index of current entry */ + FsdirLevel *aLvl; /* Hierarchy of directories being traversed */ - const char *zBase; - int nBase; + const char *zBase; + int nBase; - struct stat sStat; /* Current lstat() results */ - char *zPath; /* Path to current entry */ - sqlite3_int64 iRowid; /* Current rowid */ + struct stat sStat; /* Current lstat() results */ + char *zPath; /* Path to current entry */ + sqlite3_int64 iRowid; /* Current rowid */ }; typedef struct fsdir_tab fsdir_tab; struct fsdir_tab { - sqlite3_vtab base; /* Base class - must be first */ + sqlite3_vtab base; /* Base class - must be first */ }; /* ** Construct a new fsdir virtual table object. */ static int fsdirConnect( - sqlite3 *db, - void *pAux, - int argc, const char *const*argv, - sqlite3_vtab **ppVtab, - char **pzErr + sqlite3 *db, + void *pAux, + int argc, const char *const*argv, + sqlite3_vtab **ppVtab, + char **pzErr ){ - fsdir_tab *pNew = 0; - int rc; - (void)pAux; - (void)argc; - (void)argv; - (void)pzErr; - rc = sqlite3_declare_vtab(db, "CREATE TABLE x" FSDIR_SCHEMA); - if( rc==SQLITE_OK ){ - pNew = (fsdir_tab*)sqlite3_malloc( sizeof(*pNew) ); - if( pNew==0 ) return SQLITE_NOMEM; - memset(pNew, 0, sizeof(*pNew)); - sqlite3_vtab_config(db, SQLITE_VTAB_DIRECTONLY); - } - *ppVtab = (sqlite3_vtab*)pNew; - return rc; + fsdir_tab *pNew = 0; + int rc; + (void)pAux; + (void)argc; + (void)argv; + (void)pzErr; + rc = sqlite3_declare_vtab(db, "CREATE TABLE x" FSDIR_SCHEMA); + if( rc==SQLITE_OK ){ + pNew = (fsdir_tab*)sqlite3_malloc( sizeof(*pNew) ); + if( pNew==0 ) return SQLITE_NOMEM; + memset(pNew, 0, sizeof(*pNew)); + sqlite3_vtab_config(db, SQLITE_VTAB_DIRECTONLY); + } + *ppVtab = (sqlite3_vtab*)pNew; + return rc; } /* ** This method is the destructor for fsdir vtab objects. */ static int fsdirDisconnect(sqlite3_vtab *pVtab){ - sqlite3_free(pVtab); - return SQLITE_OK; + sqlite3_free(pVtab); + return SQLITE_OK; } /* ** Constructor for a new fsdir_cursor object. */ static int fsdirOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){ - fsdir_cursor *pCur; - (void)p; - pCur = sqlite3_malloc( sizeof(*pCur) ); - if( pCur==0 ) return SQLITE_NOMEM; - memset(pCur, 0, sizeof(*pCur)); - pCur->iLvl = -1; - *ppCursor = &pCur->base; - return SQLITE_OK; + fsdir_cursor *pCur; + (void)p; + pCur = sqlite3_malloc( sizeof(*pCur) ); + if( pCur==0 ) return SQLITE_NOMEM; + memset(pCur, 0, sizeof(*pCur)); + pCur->iLvl = -1; + *ppCursor = &pCur->base; + return SQLITE_OK; } /* @@ -2792,32 +2792,32 @@ static int fsdirOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){ ** by fsdirOpen(). */ static void fsdirResetCursor(fsdir_cursor *pCur){ - int i; - for(i=0; i<=pCur->iLvl; i++){ - FsdirLevel *pLvl = &pCur->aLvl[i]; - if( pLvl->pDir ) closedir(pLvl->pDir); - sqlite3_free(pLvl->zDir); - } - sqlite3_free(pCur->zPath); - sqlite3_free(pCur->aLvl); - pCur->aLvl = 0; - pCur->zPath = 0; - pCur->zBase = 0; - pCur->nBase = 0; - pCur->nLvl = 0; - pCur->iLvl = -1; - pCur->iRowid = 1; + int i; + for(i=0; i<=pCur->iLvl; i++){ + FsdirLevel *pLvl = &pCur->aLvl[i]; + if( pLvl->pDir ) closedir(pLvl->pDir); + sqlite3_free(pLvl->zDir); + } + sqlite3_free(pCur->zPath); + sqlite3_free(pCur->aLvl); + pCur->aLvl = 0; + pCur->zPath = 0; + pCur->zBase = 0; + pCur->nBase = 0; + pCur->nLvl = 0; + pCur->iLvl = -1; + pCur->iRowid = 1; } /* ** Destructor for an fsdir_cursor. */ static int fsdirClose(sqlite3_vtab_cursor *cur){ - fsdir_cursor *pCur = (fsdir_cursor*)cur; + fsdir_cursor *pCur = (fsdir_cursor*)cur; - fsdirResetCursor(pCur); - sqlite3_free(pCur); - return SQLITE_OK; + fsdirResetCursor(pCur); + sqlite3_free(pCur); + return SQLITE_OK; } /* @@ -2825,10 +2825,10 @@ static int fsdirClose(sqlite3_vtab_cursor *cur){ ** pCur to the results of vprintf(zFmt, ...). */ static void fsdirSetErrmsg(fsdir_cursor *pCur, const char *zFmt, ...){ - va_list ap; - va_start(ap, zFmt); - pCur->base.pVtab->zErrMsg = sqlite3_vmprintf(zFmt, ap); - va_end(ap); + va_list ap; + va_start(ap, zFmt); + pCur->base.pVtab->zErrMsg = sqlite3_vmprintf(zFmt, ap); + va_end(ap); } @@ -2836,63 +2836,63 @@ static void fsdirSetErrmsg(fsdir_cursor *pCur, const char *zFmt, ...){ ** Advance an fsdir_cursor to its next row of output. */ static int fsdirNext(sqlite3_vtab_cursor *cur){ - fsdir_cursor *pCur = (fsdir_cursor*)cur; - mode_t m = pCur->sStat.st_mode; - - pCur->iRowid++; - if( S_ISDIR(m) ){ - /* Descend into this directory */ - int iNew = pCur->iLvl + 1; - FsdirLevel *pLvl; - if( iNew>=pCur->nLvl ){ - int nNew = iNew+1; - sqlite3_int64 nByte = nNew*sizeof(FsdirLevel); - FsdirLevel *aNew = (FsdirLevel*)sqlite3_realloc64(pCur->aLvl, nByte); - if( aNew==0 ) return SQLITE_NOMEM; - memset(&aNew[pCur->nLvl], 0, sizeof(FsdirLevel)*(nNew-pCur->nLvl)); - pCur->aLvl = aNew; - pCur->nLvl = nNew; - } - pCur->iLvl = iNew; - pLvl = &pCur->aLvl[iNew]; - - pLvl->zDir = pCur->zPath; - pCur->zPath = 0; - pLvl->pDir = opendir(pLvl->zDir); - if( pLvl->pDir==0 ){ - fsdirSetErrmsg(pCur, "cannot read directory: %s", pCur->zPath); - return SQLITE_ERROR; - } + fsdir_cursor *pCur = (fsdir_cursor*)cur; + mode_t m = pCur->sStat.st_mode; + + pCur->iRowid++; + if( S_ISDIR(m) ){ + /* Descend into this directory */ + int iNew = pCur->iLvl + 1; + FsdirLevel *pLvl; + if( iNew>=pCur->nLvl ){ + int nNew = iNew+1; + sqlite3_int64 nByte = nNew*sizeof(FsdirLevel); + FsdirLevel *aNew = (FsdirLevel*)sqlite3_realloc64(pCur->aLvl, nByte); + if( aNew==0 ) return SQLITE_NOMEM; + memset(&aNew[pCur->nLvl], 0, sizeof(FsdirLevel)*(nNew-pCur->nLvl)); + pCur->aLvl = aNew; + pCur->nLvl = nNew; + } + pCur->iLvl = iNew; + pLvl = &pCur->aLvl[iNew]; + + pLvl->zDir = pCur->zPath; + pCur->zPath = 0; + pLvl->pDir = opendir(pLvl->zDir); + if( pLvl->pDir==0 ){ + fsdirSetErrmsg(pCur, "cannot read directory: %s", pCur->zPath); + return SQLITE_ERROR; } + } - while( pCur->iLvl>=0 ){ - FsdirLevel *pLvl = &pCur->aLvl[pCur->iLvl]; - struct dirent *pEntry = readdir(pLvl->pDir); - if( pEntry ){ - if( pEntry->d_name[0]=='.' ){ - if( pEntry->d_name[1]=='.' && pEntry->d_name[2]=='\0' ) continue; - if( pEntry->d_name[1]=='\0' ) continue; - } - sqlite3_free(pCur->zPath); - pCur->zPath = sqlite3_mprintf("%s/%s", pLvl->zDir, pEntry->d_name); - if( pCur->zPath==0 ) return SQLITE_NOMEM; - if( fileLinkStat(pCur->zPath, &pCur->sStat) ){ - fsdirSetErrmsg(pCur, "cannot stat file: %s", pCur->zPath); - return SQLITE_ERROR; - } - return SQLITE_OK; - } - closedir(pLvl->pDir); - sqlite3_free(pLvl->zDir); - pLvl->pDir = 0; - pLvl->zDir = 0; - pCur->iLvl--; + while( pCur->iLvl>=0 ){ + FsdirLevel *pLvl = &pCur->aLvl[pCur->iLvl]; + struct dirent *pEntry = readdir(pLvl->pDir); + if( pEntry ){ + if( pEntry->d_name[0]=='.' ){ + if( pEntry->d_name[1]=='.' && pEntry->d_name[2]=='\0' ) continue; + if( pEntry->d_name[1]=='\0' ) continue; + } + sqlite3_free(pCur->zPath); + pCur->zPath = sqlite3_mprintf("%s/%s", pLvl->zDir, pEntry->d_name); + if( pCur->zPath==0 ) return SQLITE_NOMEM; + if( fileLinkStat(pCur->zPath, &pCur->sStat) ){ + fsdirSetErrmsg(pCur, "cannot stat file: %s", pCur->zPath); + return SQLITE_ERROR; + } + return SQLITE_OK; } + closedir(pLvl->pDir); + sqlite3_free(pLvl->zDir); + pLvl->pDir = 0; + pLvl->zDir = 0; + pCur->iLvl--; + } - /* EOF */ - sqlite3_free(pCur->zPath); - pCur->zPath = 0; - return SQLITE_OK; + /* EOF */ + sqlite3_free(pCur->zPath); + pCur->zPath = 0; + return SQLITE_OK; } /* @@ -2900,63 +2900,63 @@ static int fsdirNext(sqlite3_vtab_cursor *cur){ ** is currently pointing. */ static int fsdirColumn( - sqlite3_vtab_cursor *cur, /* The cursor */ - sqlite3_context *ctx, /* First argument to sqlite3_result_...() */ - int i /* Which column to return */ + sqlite3_vtab_cursor *cur, /* The cursor */ + sqlite3_context *ctx, /* First argument to sqlite3_result_...() */ + int i /* Which column to return */ ){ - fsdir_cursor *pCur = (fsdir_cursor*)cur; - switch( i ){ - case FSDIR_COLUMN_NAME: { - sqlite3_result_text(ctx, &pCur->zPath[pCur->nBase], -1, SQLITE_TRANSIENT); - break; - } + fsdir_cursor *pCur = (fsdir_cursor*)cur; + switch( i ){ + case FSDIR_COLUMN_NAME: { + sqlite3_result_text(ctx, &pCur->zPath[pCur->nBase], -1, SQLITE_TRANSIENT); + break; + } - case FSDIR_COLUMN_MODE: - sqlite3_result_int64(ctx, pCur->sStat.st_mode); - break; + case FSDIR_COLUMN_MODE: + sqlite3_result_int64(ctx, pCur->sStat.st_mode); + break; - case FSDIR_COLUMN_MTIME: - sqlite3_result_int64(ctx, pCur->sStat.st_mtime); - break; + case FSDIR_COLUMN_MTIME: + sqlite3_result_int64(ctx, pCur->sStat.st_mtime); + break; - case FSDIR_COLUMN_DATA: { - mode_t m = pCur->sStat.st_mode; - if( S_ISDIR(m) ){ - sqlite3_result_null(ctx); + case FSDIR_COLUMN_DATA: { + mode_t m = pCur->sStat.st_mode; + if( S_ISDIR(m) ){ + sqlite3_result_null(ctx); #if !defined(_WIN32) && !defined(WIN32) - }else if( S_ISLNK(m) ){ - char aStatic[64]; - char *aBuf = aStatic; - sqlite3_int64 nBuf = 64; - int n; - - while( 1 ){ - n = readlink(pCur->zPath, aBuf, nBuf); - if( nzPath, aBuf, nBuf); + if( nzPath); - } - } - case FSDIR_COLUMN_PATH: - default: { - /* The FSDIR_COLUMN_PATH and FSDIR_COLUMN_DIR are input parameters. + }else{ + readFileContents(ctx, pCur->zPath); + } + } + case FSDIR_COLUMN_PATH: + default: { + /* The FSDIR_COLUMN_PATH and FSDIR_COLUMN_DIR are input parameters. ** always return their values as NULL */ - break; - } + break; } - return SQLITE_OK; + } + return SQLITE_OK; } /* @@ -2965,9 +2965,9 @@ static int fsdirColumn( ** row a value 1 more than that of the previous. */ static int fsdirRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){ - fsdir_cursor *pCur = (fsdir_cursor*)cur; - *pRowid = pCur->iRowid; - return SQLITE_OK; + fsdir_cursor *pCur = (fsdir_cursor*)cur; + *pRowid = pCur->iRowid; + return SQLITE_OK; } /* @@ -2975,8 +2975,8 @@ static int fsdirRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){ ** row of output. */ static int fsdirEof(sqlite3_vtab_cursor *cur){ - fsdir_cursor *pCur = (fsdir_cursor*)cur; - return (pCur->zPath==0); + fsdir_cursor *pCur = (fsdir_cursor*)cur; + return (pCur->zPath==0); } /* @@ -2986,45 +2986,45 @@ static int fsdirEof(sqlite3_vtab_cursor *cur){ ** idxNum==2 Both PATH and DIR supplied */ static int fsdirFilter( - sqlite3_vtab_cursor *cur, - int idxNum, const char *idxStr, - int argc, sqlite3_value **argv + sqlite3_vtab_cursor *cur, + int idxNum, const char *idxStr, + int argc, sqlite3_value **argv ){ - const char *zDir = 0; - fsdir_cursor *pCur = (fsdir_cursor*)cur; - (void)idxStr; - fsdirResetCursor(pCur); - - if( idxNum==0 ){ - fsdirSetErrmsg(pCur, "table function fsdir requires an argument"); - return SQLITE_ERROR; - } + const char *zDir = 0; + fsdir_cursor *pCur = (fsdir_cursor*)cur; + (void)idxStr; + fsdirResetCursor(pCur); - assert( argc==idxNum && (argc==1 || argc==2) ); - zDir = (const char*)sqlite3_value_text(argv[0]); - if( zDir==0 ){ - fsdirSetErrmsg(pCur, "table function fsdir requires a non-NULL argument"); - return SQLITE_ERROR; - } - if( argc==2 ){ - pCur->zBase = (const char*)sqlite3_value_text(argv[1]); - } - if( pCur->zBase ){ - pCur->nBase = (int)strlen(pCur->zBase)+1; - pCur->zPath = sqlite3_mprintf("%s/%s", pCur->zBase, zDir); - }else{ - pCur->zPath = sqlite3_mprintf("%s", zDir); - } + if( idxNum==0 ){ + fsdirSetErrmsg(pCur, "table function fsdir requires an argument"); + return SQLITE_ERROR; + } - if( pCur->zPath==0 ){ - return SQLITE_NOMEM; - } - if( fileLinkStat(pCur->zPath, &pCur->sStat) ){ - fsdirSetErrmsg(pCur, "cannot stat file: %s", pCur->zPath); - return SQLITE_ERROR; - } + assert( argc==idxNum && (argc==1 || argc==2) ); + zDir = (const char*)sqlite3_value_text(argv[0]); + if( zDir==0 ){ + fsdirSetErrmsg(pCur, "table function fsdir requires a non-NULL argument"); + return SQLITE_ERROR; + } + if( argc==2 ){ + pCur->zBase = (const char*)sqlite3_value_text(argv[1]); + } + if( pCur->zBase ){ + pCur->nBase = (int)strlen(pCur->zBase)+1; + pCur->zPath = sqlite3_mprintf("%s/%s", pCur->zBase, zDir); + }else{ + pCur->zPath = sqlite3_mprintf("%s", zDir); + } + + if( pCur->zPath==0 ){ + return SQLITE_NOMEM; + } + if( fileLinkStat(pCur->zPath, &pCur->sStat) ){ + fsdirSetErrmsg(pCur, "cannot stat file: %s", pCur->zPath); + return SQLITE_ERROR; + } - return SQLITE_OK; + return SQLITE_OK; } /* @@ -3042,101 +3042,101 @@ static int fsdirFilter( ** (2) Path is in argv[0] and dir is in argv[1] */ static int fsdirBestIndex( - sqlite3_vtab *tab, - sqlite3_index_info *pIdxInfo + sqlite3_vtab *tab, + sqlite3_index_info *pIdxInfo ){ - int i; /* Loop over constraints */ - int idxPath = -1; /* Index in pIdxInfo->aConstraint of PATH= */ - int idxDir = -1; /* Index in pIdxInfo->aConstraint of DIR= */ - int seenPath = 0; /* True if an unusable PATH= constraint is seen */ - int seenDir = 0; /* True if an unusable DIR= constraint is seen */ - const struct sqlite3_index_constraint *pConstraint; - - (void)tab; - pConstraint = pIdxInfo->aConstraint; - for(i=0; inConstraint; i++, pConstraint++){ - if( pConstraint->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue; - switch( pConstraint->iColumn ){ - case FSDIR_COLUMN_PATH: { - if( pConstraint->usable ){ - idxPath = i; - seenPath = 0; - }else if( idxPath<0 ){ - seenPath = 1; - } - break; - } - case FSDIR_COLUMN_DIR: { - if( pConstraint->usable ){ - idxDir = i; - seenDir = 0; - }else if( idxDir<0 ){ - seenDir = 1; - } - break; - } - } - } - if( seenPath || seenDir ){ - /* If input parameters are unusable, disallow this plan */ - return SQLITE_CONSTRAINT; - } - - if( idxPath<0 ){ - pIdxInfo->idxNum = 0; - /* The pIdxInfo->estimatedCost should have been initialized to a huge + int i; /* Loop over constraints */ + int idxPath = -1; /* Index in pIdxInfo->aConstraint of PATH= */ + int idxDir = -1; /* Index in pIdxInfo->aConstraint of DIR= */ + int seenPath = 0; /* True if an unusable PATH= constraint is seen */ + int seenDir = 0; /* True if an unusable DIR= constraint is seen */ + const struct sqlite3_index_constraint *pConstraint; + + (void)tab; + pConstraint = pIdxInfo->aConstraint; + for(i=0; inConstraint; i++, pConstraint++){ + if( pConstraint->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue; + switch( pConstraint->iColumn ){ + case FSDIR_COLUMN_PATH: { + if( pConstraint->usable ){ + idxPath = i; + seenPath = 0; + }else if( idxPath<0 ){ + seenPath = 1; + } + break; + } + case FSDIR_COLUMN_DIR: { + if( pConstraint->usable ){ + idxDir = i; + seenDir = 0; + }else if( idxDir<0 ){ + seenDir = 1; + } + break; + } + } + } + if( seenPath || seenDir ){ + /* If input parameters are unusable, disallow this plan */ + return SQLITE_CONSTRAINT; + } + + if( idxPath<0 ){ + pIdxInfo->idxNum = 0; + /* The pIdxInfo->estimatedCost should have been initialized to a huge ** number. Leave it unchanged. */ - pIdxInfo->estimatedRows = 0x7fffffff; + pIdxInfo->estimatedRows = 0x7fffffff; + }else{ + pIdxInfo->aConstraintUsage[idxPath].omit = 1; + pIdxInfo->aConstraintUsage[idxPath].argvIndex = 1; + if( idxDir>=0 ){ + pIdxInfo->aConstraintUsage[idxDir].omit = 1; + pIdxInfo->aConstraintUsage[idxDir].argvIndex = 2; + pIdxInfo->idxNum = 2; + pIdxInfo->estimatedCost = 10.0; }else{ - pIdxInfo->aConstraintUsage[idxPath].omit = 1; - pIdxInfo->aConstraintUsage[idxPath].argvIndex = 1; - if( idxDir>=0 ){ - pIdxInfo->aConstraintUsage[idxDir].omit = 1; - pIdxInfo->aConstraintUsage[idxDir].argvIndex = 2; - pIdxInfo->idxNum = 2; - pIdxInfo->estimatedCost = 10.0; - }else{ - pIdxInfo->idxNum = 1; - pIdxInfo->estimatedCost = 100.0; - } + pIdxInfo->idxNum = 1; + pIdxInfo->estimatedCost = 100.0; } + } - return SQLITE_OK; + return SQLITE_OK; } /* ** Register the "fsdir" virtual table. */ static int fsdirRegister(sqlite3 *db){ - static sqlite3_module fsdirModule = { - 0, /* iVersion */ - 0, /* xCreate */ - fsdirConnect, /* xConnect */ - fsdirBestIndex, /* xBestIndex */ - fsdirDisconnect, /* xDisconnect */ - 0, /* xDestroy */ - fsdirOpen, /* xOpen - open a cursor */ - fsdirClose, /* xClose - close a cursor */ - fsdirFilter, /* xFilter - configure scan constraints */ - fsdirNext, /* xNext - advance a cursor */ - fsdirEof, /* xEof - check for end of scan */ - fsdirColumn, /* xColumn - read data */ - fsdirRowid, /* xRowid - read data */ - 0, /* xUpdate */ - 0, /* xBegin */ - 0, /* xSync */ - 0, /* xCommit */ - 0, /* xRollback */ - 0, /* xFindMethod */ - 0, /* xRename */ - 0, /* xSavepoint */ - 0, /* xRelease */ - 0, /* xRollbackTo */ - 0, /* xShadowName */ - }; + static sqlite3_module fsdirModule = { + 0, /* iVersion */ + 0, /* xCreate */ + fsdirConnect, /* xConnect */ + fsdirBestIndex, /* xBestIndex */ + fsdirDisconnect, /* xDisconnect */ + 0, /* xDestroy */ + fsdirOpen, /* xOpen - open a cursor */ + fsdirClose, /* xClose - close a cursor */ + fsdirFilter, /* xFilter - configure scan constraints */ + fsdirNext, /* xNext - advance a cursor */ + fsdirEof, /* xEof - check for end of scan */ + fsdirColumn, /* xColumn - read data */ + fsdirRowid, /* xRowid - read data */ + 0, /* xUpdate */ + 0, /* xBegin */ + 0, /* xSync */ + 0, /* xCommit */ + 0, /* xRollback */ + 0, /* xFindMethod */ + 0, /* xRename */ + 0, /* xSavepoint */ + 0, /* xRelease */ + 0, /* xRollbackTo */ + 0, /* xShadowName */ + }; - int rc = sqlite3_create_module(db, "fsdir", &fsdirModule, 0); - return rc; + int rc = sqlite3_create_module(db, "fsdir", &fsdirModule, 0); + return rc; } #else /* SQLITE_OMIT_VIRTUALTABLE */ # define fsdirRegister(x) SQLITE_OK @@ -3146,29 +3146,29 @@ static int fsdirRegister(sqlite3 *db){ #endif int sqlite3_fileio_init( - sqlite3 *db, - char **pzErrMsg, - const sqlite3_api_routines *pApi + sqlite3 *db, + char **pzErrMsg, + const sqlite3_api_routines *pApi ){ - int rc = SQLITE_OK; - SQLITE_EXTENSION_INIT2(pApi); - (void)pzErrMsg; /* Unused parameter */ - rc = sqlite3_create_function(db, "readfile", 1, - SQLITE_UTF8|SQLITE_DIRECTONLY, 0, - readfileFunc, 0, 0); - if( rc==SQLITE_OK ){ - rc = sqlite3_create_function(db, "writefile", -1, - SQLITE_UTF8|SQLITE_DIRECTONLY, 0, - writefileFunc, 0, 0); - } - if( rc==SQLITE_OK ){ - rc = sqlite3_create_function(db, "lsmode", 1, SQLITE_UTF8, 0, - lsModeFunc, 0, 0); - } - if( rc==SQLITE_OK ){ - rc = fsdirRegister(db); - } - return rc; + int rc = SQLITE_OK; + SQLITE_EXTENSION_INIT2(pApi); + (void)pzErrMsg; /* Unused parameter */ + rc = sqlite3_create_function(db, "readfile", 1, + SQLITE_UTF8|SQLITE_DIRECTONLY, 0, + readfileFunc, 0, 0); + if( rc==SQLITE_OK ){ + rc = sqlite3_create_function(db, "writefile", -1, + SQLITE_UTF8|SQLITE_DIRECTONLY, 0, + writefileFunc, 0, 0); + } + if( rc==SQLITE_OK ){ + rc = sqlite3_create_function(db, "lsmode", 1, SQLITE_UTF8, 0, + lsModeFunc, 0, 0); + } + if( rc==SQLITE_OK ){ + rc = fsdirRegister(db); + } + return rc; } #if defined(FILEIO_WIN32_DLL) && (defined(_WIN32) || defined(WIN32)) @@ -3229,8 +3229,8 @@ SQLITE_EXTENSION_INIT1 */ typedef struct completion_vtab completion_vtab; struct completion_vtab { - sqlite3_vtab base; /* Base class - must be first */ - sqlite3 *db; /* Database connection for this completion vtab */ + sqlite3_vtab base; /* Base class - must be first */ + sqlite3 *db; /* Database connection for this completion vtab */ }; /* completion_cursor is a subclass of sqlite3_vtab_cursor which will @@ -3239,17 +3239,17 @@ struct completion_vtab { */ typedef struct completion_cursor completion_cursor; struct completion_cursor { - sqlite3_vtab_cursor base; /* Base class - must be first */ - sqlite3 *db; /* Database connection for this cursor */ - int nPrefix, nLine; /* Number of bytes in zPrefix and zLine */ - char *zPrefix; /* The prefix for the word we want to complete */ - char *zLine; /* The whole that we want to complete */ - const char *zCurrentRow; /* Current output row */ - int szRow; /* Length of the zCurrentRow string */ - sqlite3_stmt *pStmt; /* Current statement */ - sqlite3_int64 iRowid; /* The rowid */ - int ePhase; /* Current phase */ - int j; /* inter-phase counter */ + sqlite3_vtab_cursor base; /* Base class - must be first */ + sqlite3 *db; /* Database connection for this cursor */ + int nPrefix, nLine; /* Number of bytes in zPrefix and zLine */ + char *zPrefix; /* The prefix for the word we want to complete */ + char *zLine; /* The whole that we want to complete */ + const char *zCurrentRow; /* Current output row */ + int szRow; /* Length of the zCurrentRow string */ + sqlite3_stmt *pStmt; /* Current statement */ + sqlite3_int64 iRowid; /* The rowid */ + int ePhase; /* Current phase */ + int j; /* inter-phase counter */ }; /* Values for ePhase: @@ -3281,19 +3281,19 @@ struct completion_cursor { ** result set of queries against completion will look like. */ static int completionConnect( - sqlite3 *db, - void *pAux, - int argc, const char *const*argv, - sqlite3_vtab **ppVtab, - char **pzErr + sqlite3 *db, + void *pAux, + int argc, const char *const*argv, + sqlite3_vtab **ppVtab, + char **pzErr ){ - completion_vtab *pNew; - int rc; + completion_vtab *pNew; + int rc; - (void)(pAux); /* Unused parameter */ - (void)(argc); /* Unused parameter */ - (void)(argv); /* Unused parameter */ - (void)(pzErr); /* Unused parameter */ + (void)(pAux); /* Unused parameter */ + (void)(argc); /* Unused parameter */ + (void)(argv); /* Unused parameter */ + (void)(pzErr); /* Unused parameter */ /* Column numbers */ #define COMPLETION_COLUMN_CANDIDATE 0 /* Suggested completion of the input */ @@ -3301,62 +3301,62 @@ static int completionConnect( #define COMPLETION_COLUMN_WHOLELINE 2 /* Entire line seen so far */ #define COMPLETION_COLUMN_PHASE 3 /* ePhase - used for debugging only */ - sqlite3_vtab_config(db, SQLITE_VTAB_INNOCUOUS); - rc = sqlite3_declare_vtab(db, - "CREATE TABLE x(" - " candidate TEXT," - " prefix TEXT HIDDEN," - " wholeline TEXT HIDDEN," - " phase INT HIDDEN" /* Used for debugging only */ - ")"); - if( rc==SQLITE_OK ){ - pNew = sqlite3_malloc( sizeof(*pNew) ); - *ppVtab = (sqlite3_vtab*)pNew; - if( pNew==0 ) return SQLITE_NOMEM; - memset(pNew, 0, sizeof(*pNew)); - pNew->db = db; - } - return rc; + sqlite3_vtab_config(db, SQLITE_VTAB_INNOCUOUS); + rc = sqlite3_declare_vtab(db, + "CREATE TABLE x(" + " candidate TEXT," + " prefix TEXT HIDDEN," + " wholeline TEXT HIDDEN," + " phase INT HIDDEN" /* Used for debugging only */ + ")"); + if( rc==SQLITE_OK ){ + pNew = sqlite3_malloc( sizeof(*pNew) ); + *ppVtab = (sqlite3_vtab*)pNew; + if( pNew==0 ) return SQLITE_NOMEM; + memset(pNew, 0, sizeof(*pNew)); + pNew->db = db; + } + return rc; } /* ** This method is the destructor for completion_cursor objects. */ static int completionDisconnect(sqlite3_vtab *pVtab){ - sqlite3_free(pVtab); - return SQLITE_OK; + sqlite3_free(pVtab); + return SQLITE_OK; } /* ** Constructor for a new completion_cursor object. */ static int completionOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){ - completion_cursor *pCur; - pCur = sqlite3_malloc( sizeof(*pCur) ); - if( pCur==0 ) return SQLITE_NOMEM; - memset(pCur, 0, sizeof(*pCur)); - pCur->db = ((completion_vtab*)p)->db; - *ppCursor = &pCur->base; - return SQLITE_OK; + completion_cursor *pCur; + pCur = sqlite3_malloc( sizeof(*pCur) ); + if( pCur==0 ) return SQLITE_NOMEM; + memset(pCur, 0, sizeof(*pCur)); + pCur->db = ((completion_vtab*)p)->db; + *ppCursor = &pCur->base; + return SQLITE_OK; } /* ** Reset the completion_cursor. */ static void completionCursorReset(completion_cursor *pCur){ - sqlite3_free(pCur->zPrefix); pCur->zPrefix = 0; pCur->nPrefix = 0; - sqlite3_free(pCur->zLine); pCur->zLine = 0; pCur->nLine = 0; - sqlite3_finalize(pCur->pStmt); pCur->pStmt = 0; - pCur->j = 0; + sqlite3_free(pCur->zPrefix); pCur->zPrefix = 0; pCur->nPrefix = 0; + sqlite3_free(pCur->zLine); pCur->zLine = 0; pCur->nLine = 0; + sqlite3_finalize(pCur->pStmt); pCur->pStmt = 0; + pCur->j = 0; } /* ** Destructor for a completion_cursor. */ static int completionClose(sqlite3_vtab_cursor *cur){ - completionCursorReset((completion_cursor*)cur); - sqlite3_free(cur); - return SQLITE_OK; + completionCursorReset((completion_cursor*)cur); + sqlite3_free(cur); + return SQLITE_OK; } /* @@ -3374,107 +3374,107 @@ static int completionClose(sqlite3_vtab_cursor *cur){ ** keywords based on what would be legal at the current point of input. */ static int completionNext(sqlite3_vtab_cursor *cur){ - completion_cursor *pCur = (completion_cursor*)cur; - int eNextPhase = 0; /* Next phase to try if current phase reaches end */ - int iCol = -1; /* If >=0, step pCur->pStmt and use the i-th column */ - pCur->iRowid++; - while( pCur->ePhase!=COMPLETION_EOF ){ - switch( pCur->ePhase ){ - case COMPLETION_KEYWORDS: { - if( pCur->j >= sqlite3_keyword_count() ){ - pCur->zCurrentRow = 0; - pCur->ePhase = COMPLETION_DATABASES; - }else{ - sqlite3_keyword_name(pCur->j++, &pCur->zCurrentRow, &pCur->szRow); - } - iCol = -1; - break; - } - case COMPLETION_DATABASES: { - if( pCur->pStmt==0 ){ - sqlite3_prepare_v2(pCur->db, "PRAGMA database_list", -1, - &pCur->pStmt, 0); - } - iCol = 1; - eNextPhase = COMPLETION_TABLES; - break; - } - case COMPLETION_TABLES: { - if( pCur->pStmt==0 ){ - sqlite3_stmt *pS2; - char *zSql = 0; - const char *zSep = ""; - sqlite3_prepare_v2(pCur->db, "PRAGMA database_list", -1, &pS2, 0); - while( sqlite3_step(pS2)==SQLITE_ROW ){ - const char *zDb = (const char*)sqlite3_column_text(pS2, 1); - zSql = sqlite3_mprintf( - "%z%s" - "SELECT name FROM \"%w\".sqlite_schema", - zSql, zSep, zDb - ); - if( zSql==0 ) return SQLITE_NOMEM; - zSep = " UNION "; - } - sqlite3_finalize(pS2); - sqlite3_prepare_v2(pCur->db, zSql, -1, &pCur->pStmt, 0); - sqlite3_free(zSql); - } - iCol = 0; - eNextPhase = COMPLETION_COLUMNS; - break; - } - case COMPLETION_COLUMNS: { - if( pCur->pStmt==0 ){ - sqlite3_stmt *pS2; - char *zSql = 0; - const char *zSep = ""; - sqlite3_prepare_v2(pCur->db, "PRAGMA database_list", -1, &pS2, 0); - while( sqlite3_step(pS2)==SQLITE_ROW ){ - const char *zDb = (const char*)sqlite3_column_text(pS2, 1); - zSql = sqlite3_mprintf( - "%z%s" - "SELECT pti.name FROM \"%w\".sqlite_schema AS sm" - " JOIN pragma_table_info(sm.name,%Q) AS pti" - " WHERE sm.type='table'", - zSql, zSep, zDb, zDb - ); - if( zSql==0 ) return SQLITE_NOMEM; - zSep = " UNION "; - } - sqlite3_finalize(pS2); - sqlite3_prepare_v2(pCur->db, zSql, -1, &pCur->pStmt, 0); - sqlite3_free(zSql); - } - iCol = 0; - eNextPhase = COMPLETION_EOF; - break; - } - } - if( iCol<0 ){ - /* This case is when the phase presets zCurrentRow */ - if( pCur->zCurrentRow==0 ) continue; + completion_cursor *pCur = (completion_cursor*)cur; + int eNextPhase = 0; /* Next phase to try if current phase reaches end */ + int iCol = -1; /* If >=0, step pCur->pStmt and use the i-th column */ + pCur->iRowid++; + while( pCur->ePhase!=COMPLETION_EOF ){ + switch( pCur->ePhase ){ + case COMPLETION_KEYWORDS: { + if( pCur->j >= sqlite3_keyword_count() ){ + pCur->zCurrentRow = 0; + pCur->ePhase = COMPLETION_DATABASES; }else{ - if( sqlite3_step(pCur->pStmt)==SQLITE_ROW ){ - /* Extract the next row of content */ - pCur->zCurrentRow = (const char*)sqlite3_column_text(pCur->pStmt, iCol); - pCur->szRow = sqlite3_column_bytes(pCur->pStmt, iCol); - }else{ - /* When all rows are finished, advance to the next phase */ - sqlite3_finalize(pCur->pStmt); - pCur->pStmt = 0; - pCur->ePhase = eNextPhase; - continue; - } - } - if( pCur->nPrefix==0 ) break; - if( pCur->nPrefix<=pCur->szRow - && sqlite3_strnicmp(pCur->zPrefix, pCur->zCurrentRow, pCur->nPrefix)==0 - ){ - break; - } + sqlite3_keyword_name(pCur->j++, &pCur->zCurrentRow, &pCur->szRow); + } + iCol = -1; + break; + } + case COMPLETION_DATABASES: { + if( pCur->pStmt==0 ){ + sqlite3_prepare_v2(pCur->db, "PRAGMA database_list", -1, + &pCur->pStmt, 0); + } + iCol = 1; + eNextPhase = COMPLETION_TABLES; + break; + } + case COMPLETION_TABLES: { + if( pCur->pStmt==0 ){ + sqlite3_stmt *pS2; + char *zSql = 0; + const char *zSep = ""; + sqlite3_prepare_v2(pCur->db, "PRAGMA database_list", -1, &pS2, 0); + while( sqlite3_step(pS2)==SQLITE_ROW ){ + const char *zDb = (const char*)sqlite3_column_text(pS2, 1); + zSql = sqlite3_mprintf( + "%z%s" + "SELECT name FROM \"%w\".sqlite_schema", + zSql, zSep, zDb + ); + if( zSql==0 ) return SQLITE_NOMEM; + zSep = " UNION "; + } + sqlite3_finalize(pS2); + sqlite3_prepare_v2(pCur->db, zSql, -1, &pCur->pStmt, 0); + sqlite3_free(zSql); + } + iCol = 0; + eNextPhase = COMPLETION_COLUMNS; + break; + } + case COMPLETION_COLUMNS: { + if( pCur->pStmt==0 ){ + sqlite3_stmt *pS2; + char *zSql = 0; + const char *zSep = ""; + sqlite3_prepare_v2(pCur->db, "PRAGMA database_list", -1, &pS2, 0); + while( sqlite3_step(pS2)==SQLITE_ROW ){ + const char *zDb = (const char*)sqlite3_column_text(pS2, 1); + zSql = sqlite3_mprintf( + "%z%s" + "SELECT pti.name FROM \"%w\".sqlite_schema AS sm" + " JOIN pragma_table_info(sm.name,%Q) AS pti" + " WHERE sm.type='table'", + zSql, zSep, zDb, zDb + ); + if( zSql==0 ) return SQLITE_NOMEM; + zSep = " UNION "; + } + sqlite3_finalize(pS2); + sqlite3_prepare_v2(pCur->db, zSql, -1, &pCur->pStmt, 0); + sqlite3_free(zSql); + } + iCol = 0; + eNextPhase = COMPLETION_EOF; + break; + } + } + if( iCol<0 ){ + /* This case is when the phase presets zCurrentRow */ + if( pCur->zCurrentRow==0 ) continue; + }else{ + if( sqlite3_step(pCur->pStmt)==SQLITE_ROW ){ + /* Extract the next row of content */ + pCur->zCurrentRow = (const char*)sqlite3_column_text(pCur->pStmt, iCol); + pCur->szRow = sqlite3_column_bytes(pCur->pStmt, iCol); + }else{ + /* When all rows are finished, advance to the next phase */ + sqlite3_finalize(pCur->pStmt); + pCur->pStmt = 0; + pCur->ePhase = eNextPhase; + continue; + } + } + if( pCur->nPrefix==0 ) break; + if( pCur->nPrefix<=pCur->szRow + && sqlite3_strnicmp(pCur->zPrefix, pCur->zCurrentRow, pCur->nPrefix)==0 + ){ + break; } + } - return SQLITE_OK; + return SQLITE_OK; } /* @@ -3482,30 +3482,30 @@ static int completionNext(sqlite3_vtab_cursor *cur){ ** is currently pointing. */ static int completionColumn( - sqlite3_vtab_cursor *cur, /* The cursor */ - sqlite3_context *ctx, /* First argument to sqlite3_result_...() */ - int i /* Which column to return */ + sqlite3_vtab_cursor *cur, /* The cursor */ + sqlite3_context *ctx, /* First argument to sqlite3_result_...() */ + int i /* Which column to return */ ){ - completion_cursor *pCur = (completion_cursor*)cur; - switch( i ){ - case COMPLETION_COLUMN_CANDIDATE: { - sqlite3_result_text(ctx, pCur->zCurrentRow, pCur->szRow,SQLITE_TRANSIENT); - break; - } - case COMPLETION_COLUMN_PREFIX: { - sqlite3_result_text(ctx, pCur->zPrefix, -1, SQLITE_TRANSIENT); - break; - } - case COMPLETION_COLUMN_WHOLELINE: { - sqlite3_result_text(ctx, pCur->zLine, -1, SQLITE_TRANSIENT); - break; - } - case COMPLETION_COLUMN_PHASE: { - sqlite3_result_int(ctx, pCur->ePhase); - break; - } + completion_cursor *pCur = (completion_cursor*)cur; + switch( i ){ + case COMPLETION_COLUMN_CANDIDATE: { + sqlite3_result_text(ctx, pCur->zCurrentRow, pCur->szRow,SQLITE_TRANSIENT); + break; } - return SQLITE_OK; + case COMPLETION_COLUMN_PREFIX: { + sqlite3_result_text(ctx, pCur->zPrefix, -1, SQLITE_TRANSIENT); + break; + } + case COMPLETION_COLUMN_WHOLELINE: { + sqlite3_result_text(ctx, pCur->zLine, -1, SQLITE_TRANSIENT); + break; + } + case COMPLETION_COLUMN_PHASE: { + sqlite3_result_int(ctx, pCur->ePhase); + break; + } + } + return SQLITE_OK; } /* @@ -3513,9 +3513,9 @@ static int completionColumn( ** rowid is the same as the output value. */ static int completionRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){ - completion_cursor *pCur = (completion_cursor*)cur; - *pRowid = pCur->iRowid; - return SQLITE_OK; + completion_cursor *pCur = (completion_cursor*)cur; + *pRowid = pCur->iRowid; + return SQLITE_OK; } /* @@ -3523,55 +3523,55 @@ static int completionRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){ ** row of output. */ static int completionEof(sqlite3_vtab_cursor *cur){ - completion_cursor *pCur = (completion_cursor*)cur; - return pCur->ePhase >= COMPLETION_EOF; + completion_cursor *pCur = (completion_cursor*)cur; + return pCur->ePhase >= COMPLETION_EOF; } /* ** This method is called to "rewind" the completion_cursor object back ** to the first row of output. This method is always called at least -** once prior to any call to completionColumn() or completionRowid() or +** once prior to any call to completionColumn() or completionRowid() or ** completionEof(). */ static int completionFilter( - sqlite3_vtab_cursor *pVtabCursor, - int idxNum, const char *idxStr, - int argc, sqlite3_value **argv + sqlite3_vtab_cursor *pVtabCursor, + int idxNum, const char *idxStr, + int argc, sqlite3_value **argv ){ - completion_cursor *pCur = (completion_cursor *)pVtabCursor; - int iArg = 0; - (void)(idxStr); /* Unused parameter */ - (void)(argc); /* Unused parameter */ - completionCursorReset(pCur); - if( idxNum & 1 ){ - pCur->nPrefix = sqlite3_value_bytes(argv[iArg]); - if( pCur->nPrefix>0 ){ - pCur->zPrefix = sqlite3_mprintf("%s", sqlite3_value_text(argv[iArg])); - if( pCur->zPrefix==0 ) return SQLITE_NOMEM; - } - iArg = 1; - } - if( idxNum & 2 ){ - pCur->nLine = sqlite3_value_bytes(argv[iArg]); - if( pCur->nLine>0 ){ - pCur->zLine = sqlite3_mprintf("%s", sqlite3_value_text(argv[iArg])); - if( pCur->zLine==0 ) return SQLITE_NOMEM; - } - } - if( pCur->zLine!=0 && pCur->zPrefix==0 ){ - int i = pCur->nLine; - while( i>0 && (isalnum(pCur->zLine[i-1]) || pCur->zLine[i-1]=='_') ){ - i--; - } - pCur->nPrefix = pCur->nLine - i; - if( pCur->nPrefix>0 ){ - pCur->zPrefix = sqlite3_mprintf("%.*s", pCur->nPrefix, pCur->zLine + i); - if( pCur->zPrefix==0 ) return SQLITE_NOMEM; - } - } - pCur->iRowid = 0; - pCur->ePhase = COMPLETION_FIRST_PHASE; - return completionNext(pVtabCursor); + completion_cursor *pCur = (completion_cursor *)pVtabCursor; + int iArg = 0; + (void)(idxStr); /* Unused parameter */ + (void)(argc); /* Unused parameter */ + completionCursorReset(pCur); + if( idxNum & 1 ){ + pCur->nPrefix = sqlite3_value_bytes(argv[iArg]); + if( pCur->nPrefix>0 ){ + pCur->zPrefix = sqlite3_mprintf("%s", sqlite3_value_text(argv[iArg])); + if( pCur->zPrefix==0 ) return SQLITE_NOMEM; + } + iArg = 1; + } + if( idxNum & 2 ){ + pCur->nLine = sqlite3_value_bytes(argv[iArg]); + if( pCur->nLine>0 ){ + pCur->zLine = sqlite3_mprintf("%s", sqlite3_value_text(argv[iArg])); + if( pCur->zLine==0 ) return SQLITE_NOMEM; + } + } + if( pCur->zLine!=0 && pCur->zPrefix==0 ){ + int i = pCur->nLine; + while( i>0 && (isalnum(pCur->zLine[i-1]) || pCur->zLine[i-1]=='_') ){ + i--; + } + pCur->nPrefix = pCur->nLine - i; + if( pCur->nPrefix>0 ){ + pCur->zPrefix = sqlite3_mprintf("%.*s", pCur->nPrefix, pCur->zLine + i); + if( pCur->zPrefix==0 ) return SQLITE_NOMEM; + } + } + pCur->iRowid = 0; + pCur->ePhase = COMPLETION_FIRST_PHASE; + return completionNext(pVtabCursor); } /* @@ -3585,102 +3585,102 @@ static int completionFilter( ** is available and bit 1 is set if "wholeline" is available. */ static int completionBestIndex( - sqlite3_vtab *tab, - sqlite3_index_info *pIdxInfo + sqlite3_vtab *tab, + sqlite3_index_info *pIdxInfo ){ - int i; /* Loop over constraints */ - int idxNum = 0; /* The query plan bitmask */ - int prefixIdx = -1; /* Index of the start= constraint, or -1 if none */ - int wholelineIdx = -1; /* Index of the stop= constraint, or -1 if none */ - int nArg = 0; /* Number of arguments that completeFilter() expects */ - const struct sqlite3_index_constraint *pConstraint; - - (void)(tab); /* Unused parameter */ - pConstraint = pIdxInfo->aConstraint; - for(i=0; inConstraint; i++, pConstraint++){ - if( pConstraint->usable==0 ) continue; - if( pConstraint->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue; - switch( pConstraint->iColumn ){ - case COMPLETION_COLUMN_PREFIX: - prefixIdx = i; - idxNum |= 1; - break; - case COMPLETION_COLUMN_WHOLELINE: - wholelineIdx = i; - idxNum |= 2; - break; - } - } - if( prefixIdx>=0 ){ - pIdxInfo->aConstraintUsage[prefixIdx].argvIndex = ++nArg; - pIdxInfo->aConstraintUsage[prefixIdx].omit = 1; - } - if( wholelineIdx>=0 ){ - pIdxInfo->aConstraintUsage[wholelineIdx].argvIndex = ++nArg; - pIdxInfo->aConstraintUsage[wholelineIdx].omit = 1; - } - pIdxInfo->idxNum = idxNum; - pIdxInfo->estimatedCost = (double)5000 - 1000*nArg; - pIdxInfo->estimatedRows = 500 - 100*nArg; - return SQLITE_OK; -} - -/* -** This following structure defines all the methods for the + int i; /* Loop over constraints */ + int idxNum = 0; /* The query plan bitmask */ + int prefixIdx = -1; /* Index of the start= constraint, or -1 if none */ + int wholelineIdx = -1; /* Index of the stop= constraint, or -1 if none */ + int nArg = 0; /* Number of arguments that completeFilter() expects */ + const struct sqlite3_index_constraint *pConstraint; + + (void)(tab); /* Unused parameter */ + pConstraint = pIdxInfo->aConstraint; + for(i=0; inConstraint; i++, pConstraint++){ + if( pConstraint->usable==0 ) continue; + if( pConstraint->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue; + switch( pConstraint->iColumn ){ + case COMPLETION_COLUMN_PREFIX: + prefixIdx = i; + idxNum |= 1; + break; + case COMPLETION_COLUMN_WHOLELINE: + wholelineIdx = i; + idxNum |= 2; + break; + } + } + if( prefixIdx>=0 ){ + pIdxInfo->aConstraintUsage[prefixIdx].argvIndex = ++nArg; + pIdxInfo->aConstraintUsage[prefixIdx].omit = 1; + } + if( wholelineIdx>=0 ){ + pIdxInfo->aConstraintUsage[wholelineIdx].argvIndex = ++nArg; + pIdxInfo->aConstraintUsage[wholelineIdx].omit = 1; + } + pIdxInfo->idxNum = idxNum; + pIdxInfo->estimatedCost = (double)5000 - 1000*nArg; + pIdxInfo->estimatedRows = 500 - 100*nArg; + return SQLITE_OK; +} + +/* +** This following structure defines all the methods for the ** completion virtual table. */ static sqlite3_module completionModule = { - 0, /* iVersion */ - 0, /* xCreate */ - completionConnect, /* xConnect */ - completionBestIndex, /* xBestIndex */ - completionDisconnect, /* xDisconnect */ - 0, /* xDestroy */ - completionOpen, /* xOpen - open a cursor */ - completionClose, /* xClose - close a cursor */ - completionFilter, /* xFilter - configure scan constraints */ - completionNext, /* xNext - advance a cursor */ - completionEof, /* xEof - check for end of scan */ - completionColumn, /* xColumn - read data */ - completionRowid, /* xRowid - read data */ - 0, /* xUpdate */ - 0, /* xBegin */ - 0, /* xSync */ - 0, /* xCommit */ - 0, /* xRollback */ - 0, /* xFindMethod */ - 0, /* xRename */ - 0, /* xSavepoint */ - 0, /* xRelease */ - 0, /* xRollbackTo */ - 0 /* xShadowName */ + 0, /* iVersion */ + 0, /* xCreate */ + completionConnect, /* xConnect */ + completionBestIndex, /* xBestIndex */ + completionDisconnect, /* xDisconnect */ + 0, /* xDestroy */ + completionOpen, /* xOpen - open a cursor */ + completionClose, /* xClose - close a cursor */ + completionFilter, /* xFilter - configure scan constraints */ + completionNext, /* xNext - advance a cursor */ + completionEof, /* xEof - check for end of scan */ + completionColumn, /* xColumn - read data */ + completionRowid, /* xRowid - read data */ + 0, /* xUpdate */ + 0, /* xBegin */ + 0, /* xSync */ + 0, /* xCommit */ + 0, /* xRollback */ + 0, /* xFindMethod */ + 0, /* xRename */ + 0, /* xSavepoint */ + 0, /* xRelease */ + 0, /* xRollbackTo */ + 0 /* xShadowName */ }; #endif /* SQLITE_OMIT_VIRTUALTABLE */ int sqlite3CompletionVtabInit(sqlite3 *db){ - int rc = SQLITE_OK; + int rc = SQLITE_OK; #ifndef SQLITE_OMIT_VIRTUALTABLE - rc = sqlite3_create_module(db, "completion", &completionModule, 0); + rc = sqlite3_create_module(db, "completion", &completionModule, 0); #endif - return rc; + return rc; } #ifdef _WIN32 #endif int sqlite3_completion_init( - sqlite3 *db, - char **pzErrMsg, - const sqlite3_api_routines *pApi + sqlite3 *db, + char **pzErrMsg, + const sqlite3_api_routines *pApi ){ - int rc = SQLITE_OK; - SQLITE_EXTENSION_INIT2(pApi); - (void)(pzErrMsg); /* Unused parameter */ + int rc = SQLITE_OK; + SQLITE_EXTENSION_INIT2(pApi); + (void)(pzErrMsg); /* Unused parameter */ #ifndef SQLITE_OMIT_VIRTUALTABLE - rc = sqlite3CompletionVtabInit(db); + rc = sqlite3CompletionVtabInit(db); #endif - return rc; + return rc; } /************************* End ../ext/misc/completion.c ********************/ @@ -3813,10 +3813,10 @@ typedef struct ApndFile ApndFile; ** Or, iMark is -1 to indicate that it has not yet been written. */ struct ApndFile { - sqlite3_file base; /* Subclass. MUST BE FIRST! */ - sqlite3_int64 iPgOne; /* Offset to the start of the database */ - sqlite3_int64 iMark; /* Offset of the append mark. -1 if unwritten */ - /* Always followed by another sqlite3_file that describes the whole file */ + sqlite3_file base; /* Subclass. MUST BE FIRST! */ + sqlite3_int64 iPgOne; /* Offset to the start of the database */ + sqlite3_int64 iMark; /* Offset of the append mark. -1 if unwritten */ + /* Always followed by another sqlite3_file that describes the whole file */ }; /* @@ -3862,72 +3862,72 @@ static sqlite3_syscall_ptr apndGetSystemCall(sqlite3_vfs*, const char *z); static const char *apndNextSystemCall(sqlite3_vfs*, const char *zName); static sqlite3_vfs apnd_vfs = { - 3, /* iVersion (set when registered) */ - 0, /* szOsFile (set when registered) */ - 1024, /* mxPathname */ - 0, /* pNext */ - "apndvfs", /* zName */ - 0, /* pAppData (set when registered) */ - apndOpen, /* xOpen */ - apndDelete, /* xDelete */ - apndAccess, /* xAccess */ - apndFullPathname, /* xFullPathname */ - apndDlOpen, /* xDlOpen */ - apndDlError, /* xDlError */ - apndDlSym, /* xDlSym */ - apndDlClose, /* xDlClose */ - apndRandomness, /* xRandomness */ - apndSleep, /* xSleep */ - apndCurrentTime, /* xCurrentTime */ - apndGetLastError, /* xGetLastError */ - apndCurrentTimeInt64, /* xCurrentTimeInt64 */ - apndSetSystemCall, /* xSetSystemCall */ - apndGetSystemCall, /* xGetSystemCall */ - apndNextSystemCall /* xNextSystemCall */ + 3, /* iVersion (set when registered) */ + 0, /* szOsFile (set when registered) */ + 1024, /* mxPathname */ + 0, /* pNext */ + "apndvfs", /* zName */ + 0, /* pAppData (set when registered) */ + apndOpen, /* xOpen */ + apndDelete, /* xDelete */ + apndAccess, /* xAccess */ + apndFullPathname, /* xFullPathname */ + apndDlOpen, /* xDlOpen */ + apndDlError, /* xDlError */ + apndDlSym, /* xDlSym */ + apndDlClose, /* xDlClose */ + apndRandomness, /* xRandomness */ + apndSleep, /* xSleep */ + apndCurrentTime, /* xCurrentTime */ + apndGetLastError, /* xGetLastError */ + apndCurrentTimeInt64, /* xCurrentTimeInt64 */ + apndSetSystemCall, /* xSetSystemCall */ + apndGetSystemCall, /* xGetSystemCall */ + apndNextSystemCall /* xNextSystemCall */ }; static const sqlite3_io_methods apnd_io_methods = { - 3, /* iVersion */ - apndClose, /* xClose */ - apndRead, /* xRead */ - apndWrite, /* xWrite */ - apndTruncate, /* xTruncate */ - apndSync, /* xSync */ - apndFileSize, /* xFileSize */ - apndLock, /* xLock */ - apndUnlock, /* xUnlock */ - apndCheckReservedLock, /* xCheckReservedLock */ - apndFileControl, /* xFileControl */ - apndSectorSize, /* xSectorSize */ - apndDeviceCharacteristics, /* xDeviceCharacteristics */ - apndShmMap, /* xShmMap */ - apndShmLock, /* xShmLock */ - apndShmBarrier, /* xShmBarrier */ - apndShmUnmap, /* xShmUnmap */ - apndFetch, /* xFetch */ - apndUnfetch /* xUnfetch */ + 3, /* iVersion */ + apndClose, /* xClose */ + apndRead, /* xRead */ + apndWrite, /* xWrite */ + apndTruncate, /* xTruncate */ + apndSync, /* xSync */ + apndFileSize, /* xFileSize */ + apndLock, /* xLock */ + apndUnlock, /* xUnlock */ + apndCheckReservedLock, /* xCheckReservedLock */ + apndFileControl, /* xFileControl */ + apndSectorSize, /* xSectorSize */ + apndDeviceCharacteristics, /* xDeviceCharacteristics */ + apndShmMap, /* xShmMap */ + apndShmLock, /* xShmLock */ + apndShmBarrier, /* xShmBarrier */ + apndShmUnmap, /* xShmUnmap */ + apndFetch, /* xFetch */ + apndUnfetch /* xUnfetch */ }; /* ** Close an apnd-file. */ static int apndClose(sqlite3_file *pFile){ - pFile = ORIGFILE(pFile); - return pFile->pMethods->xClose(pFile); + pFile = ORIGFILE(pFile); + return pFile->pMethods->xClose(pFile); } /* ** Read data from an apnd-file. */ static int apndRead( - sqlite3_file *pFile, - void *zBuf, - int iAmt, - sqlite_int64 iOfst + sqlite3_file *pFile, + void *zBuf, + int iAmt, + sqlite_int64 iOfst ){ - ApndFile *paf = (ApndFile *)pFile; - pFile = ORIGFILE(pFile); - return pFile->pMethods->xRead(pFile, zBuf, iAmt, paf->iPgOne+iOfst); + ApndFile *paf = (ApndFile *)pFile; + pFile = ORIGFILE(pFile); + return pFile->pMethods->xRead(pFile, zBuf, iAmt, paf->iPgOne+iOfst); } /* @@ -3936,67 +3936,67 @@ static int apndRead( * Parameter iWriteEnd is the appendvfs-relative offset of the new mark. */ static int apndWriteMark( - ApndFile *paf, - sqlite3_file *pFile, - sqlite_int64 iWriteEnd + ApndFile *paf, + sqlite3_file *pFile, + sqlite_int64 iWriteEnd ){ - sqlite_int64 iPgOne = paf->iPgOne; - unsigned char a[APND_MARK_SIZE]; - int i = APND_MARK_FOS_SZ; - int rc; - assert(pFile == ORIGFILE(paf)); - memcpy(a, APND_MARK_PREFIX, APND_MARK_PREFIX_SZ); - while( --i >= 0 ){ - a[APND_MARK_PREFIX_SZ+i] = (unsigned char)(iPgOne & 0xff); - iPgOne >>= 8; - } - iWriteEnd += paf->iPgOne; - if( SQLITE_OK==(rc = pFile->pMethods->xWrite - (pFile, a, APND_MARK_SIZE, iWriteEnd)) ){ - paf->iMark = iWriteEnd; - } - return rc; + sqlite_int64 iPgOne = paf->iPgOne; + unsigned char a[APND_MARK_SIZE]; + int i = APND_MARK_FOS_SZ; + int rc; + assert(pFile == ORIGFILE(paf)); + memcpy(a, APND_MARK_PREFIX, APND_MARK_PREFIX_SZ); + while( --i >= 0 ){ + a[APND_MARK_PREFIX_SZ+i] = (unsigned char)(iPgOne & 0xff); + iPgOne >>= 8; + } + iWriteEnd += paf->iPgOne; + if( SQLITE_OK==(rc = pFile->pMethods->xWrite + (pFile, a, APND_MARK_SIZE, iWriteEnd)) ){ + paf->iMark = iWriteEnd; + } + return rc; } /* ** Write data to an apnd-file. */ static int apndWrite( - sqlite3_file *pFile, - const void *zBuf, - int iAmt, - sqlite_int64 iOfst + sqlite3_file *pFile, + const void *zBuf, + int iAmt, + sqlite_int64 iOfst ){ - ApndFile *paf = (ApndFile *)pFile; - sqlite_int64 iWriteEnd = iOfst + iAmt; - if( iWriteEnd>=APND_MAX_SIZE ) return SQLITE_FULL; - pFile = ORIGFILE(pFile); - /* If append-mark is absent or will be overwritten, write it. */ - if( paf->iMark < 0 || paf->iPgOne + iWriteEnd > paf->iMark ){ - int rc = apndWriteMark(paf, pFile, iWriteEnd); - if( SQLITE_OK!=rc ) return rc; - } - return pFile->pMethods->xWrite(pFile, zBuf, iAmt, paf->iPgOne+iOfst); + ApndFile *paf = (ApndFile *)pFile; + sqlite_int64 iWriteEnd = iOfst + iAmt; + if( iWriteEnd>=APND_MAX_SIZE ) return SQLITE_FULL; + pFile = ORIGFILE(pFile); + /* If append-mark is absent or will be overwritten, write it. */ + if( paf->iMark < 0 || paf->iPgOne + iWriteEnd > paf->iMark ){ + int rc = apndWriteMark(paf, pFile, iWriteEnd); + if( SQLITE_OK!=rc ) return rc; + } + return pFile->pMethods->xWrite(pFile, zBuf, iAmt, paf->iPgOne+iOfst); } /* ** Truncate an apnd-file. */ static int apndTruncate(sqlite3_file *pFile, sqlite_int64 size){ - ApndFile *paf = (ApndFile *)pFile; - pFile = ORIGFILE(pFile); - /* The append mark goes out first so truncate failure does not lose it. */ - if( SQLITE_OK!=apndWriteMark(paf, pFile, size) ) return SQLITE_IOERR; - /* Truncate underlying file just past append mark */ - return pFile->pMethods->xTruncate(pFile, paf->iMark+APND_MARK_SIZE); + ApndFile *paf = (ApndFile *)pFile; + pFile = ORIGFILE(pFile); + /* The append mark goes out first so truncate failure does not lose it. */ + if( SQLITE_OK!=apndWriteMark(paf, pFile, size) ) return SQLITE_IOERR; + /* Truncate underlying file just past append mark */ + return pFile->pMethods->xTruncate(pFile, paf->iMark+APND_MARK_SIZE); } /* ** Sync an apnd-file. */ static int apndSync(sqlite3_file *pFile, int flags){ - pFile = ORIGFILE(pFile); - return pFile->pMethods->xSync(pFile, flags); + pFile = ORIGFILE(pFile); + return pFile->pMethods->xSync(pFile, flags); } /* @@ -4004,116 +4004,116 @@ static int apndSync(sqlite3_file *pFile, int flags){ ** If the append mark is not yet there, the file-size is 0. */ static int apndFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){ - ApndFile *paf = (ApndFile *)pFile; - *pSize = ( paf->iMark >= 0 )? (paf->iMark - paf->iPgOne) : 0; - return SQLITE_OK; + ApndFile *paf = (ApndFile *)pFile; + *pSize = ( paf->iMark >= 0 )? (paf->iMark - paf->iPgOne) : 0; + return SQLITE_OK; } /* ** Lock an apnd-file. */ static int apndLock(sqlite3_file *pFile, int eLock){ - pFile = ORIGFILE(pFile); - return pFile->pMethods->xLock(pFile, eLock); + pFile = ORIGFILE(pFile); + return pFile->pMethods->xLock(pFile, eLock); } /* ** Unlock an apnd-file. */ static int apndUnlock(sqlite3_file *pFile, int eLock){ - pFile = ORIGFILE(pFile); - return pFile->pMethods->xUnlock(pFile, eLock); + pFile = ORIGFILE(pFile); + return pFile->pMethods->xUnlock(pFile, eLock); } /* ** Check if another file-handle holds a RESERVED lock on an apnd-file. */ static int apndCheckReservedLock(sqlite3_file *pFile, int *pResOut){ - pFile = ORIGFILE(pFile); - return pFile->pMethods->xCheckReservedLock(pFile, pResOut); + pFile = ORIGFILE(pFile); + return pFile->pMethods->xCheckReservedLock(pFile, pResOut); } /* ** File control method. For custom operations on an apnd-file. */ static int apndFileControl(sqlite3_file *pFile, int op, void *pArg){ - ApndFile *paf = (ApndFile *)pFile; - int rc; - pFile = ORIGFILE(pFile); - if( op==SQLITE_FCNTL_SIZE_HINT ) *(sqlite3_int64*)pArg += paf->iPgOne; - rc = pFile->pMethods->xFileControl(pFile, op, pArg); - if( rc==SQLITE_OK && op==SQLITE_FCNTL_VFSNAME ){ - *(char**)pArg = sqlite3_mprintf("apnd(%lld)/%z", paf->iPgOne,*(char**)pArg); - } - return rc; + ApndFile *paf = (ApndFile *)pFile; + int rc; + pFile = ORIGFILE(pFile); + if( op==SQLITE_FCNTL_SIZE_HINT ) *(sqlite3_int64*)pArg += paf->iPgOne; + rc = pFile->pMethods->xFileControl(pFile, op, pArg); + if( rc==SQLITE_OK && op==SQLITE_FCNTL_VFSNAME ){ + *(char**)pArg = sqlite3_mprintf("apnd(%lld)/%z", paf->iPgOne,*(char**)pArg); + } + return rc; } /* ** Return the sector-size in bytes for an apnd-file. */ static int apndSectorSize(sqlite3_file *pFile){ - pFile = ORIGFILE(pFile); - return pFile->pMethods->xSectorSize(pFile); + pFile = ORIGFILE(pFile); + return pFile->pMethods->xSectorSize(pFile); } /* ** Return the device characteristic flags supported by an apnd-file. */ static int apndDeviceCharacteristics(sqlite3_file *pFile){ - pFile = ORIGFILE(pFile); - return pFile->pMethods->xDeviceCharacteristics(pFile); + pFile = ORIGFILE(pFile); + return pFile->pMethods->xDeviceCharacteristics(pFile); } /* Create a shared memory file mapping */ static int apndShmMap( - sqlite3_file *pFile, - int iPg, - int pgsz, - int bExtend, - void volatile **pp + sqlite3_file *pFile, + int iPg, + int pgsz, + int bExtend, + void volatile **pp ){ - pFile = ORIGFILE(pFile); - return pFile->pMethods->xShmMap(pFile,iPg,pgsz,bExtend,pp); + pFile = ORIGFILE(pFile); + return pFile->pMethods->xShmMap(pFile,iPg,pgsz,bExtend,pp); } /* Perform locking on a shared-memory segment */ static int apndShmLock(sqlite3_file *pFile, int offset, int n, int flags){ - pFile = ORIGFILE(pFile); - return pFile->pMethods->xShmLock(pFile,offset,n,flags); + pFile = ORIGFILE(pFile); + return pFile->pMethods->xShmLock(pFile,offset,n,flags); } /* Memory barrier operation on shared memory */ static void apndShmBarrier(sqlite3_file *pFile){ - pFile = ORIGFILE(pFile); - pFile->pMethods->xShmBarrier(pFile); + pFile = ORIGFILE(pFile); + pFile->pMethods->xShmBarrier(pFile); } /* Unmap a shared memory segment */ static int apndShmUnmap(sqlite3_file *pFile, int deleteFlag){ - pFile = ORIGFILE(pFile); - return pFile->pMethods->xShmUnmap(pFile,deleteFlag); + pFile = ORIGFILE(pFile); + return pFile->pMethods->xShmUnmap(pFile,deleteFlag); } /* Fetch a page of a memory-mapped file */ static int apndFetch( - sqlite3_file *pFile, - sqlite3_int64 iOfst, - int iAmt, - void **pp + sqlite3_file *pFile, + sqlite3_int64 iOfst, + int iAmt, + void **pp ){ - ApndFile *p = (ApndFile *)pFile; - if( p->iMark < 0 || iOfst+iAmt > p->iMark ){ - return SQLITE_IOERR; /* Cannot read what is not yet there. */ - } - pFile = ORIGFILE(pFile); - return pFile->pMethods->xFetch(pFile, iOfst+p->iPgOne, iAmt, pp); + ApndFile *p = (ApndFile *)pFile; + if( p->iMark < 0 || iOfst+iAmt > p->iMark ){ + return SQLITE_IOERR; /* Cannot read what is not yet there. */ + } + pFile = ORIGFILE(pFile); + return pFile->pMethods->xFetch(pFile, iOfst+p->iPgOne, iAmt, pp); } /* Release a memory-mapped page */ static int apndUnfetch(sqlite3_file *pFile, sqlite3_int64 iOfst, void *pPage){ - ApndFile *p = (ApndFile *)pFile; - pFile = ORIGFILE(pFile); - return pFile->pMethods->xUnfetch(pFile, iOfst+p->iPgOne, pPage); + ApndFile *p = (ApndFile *)pFile; + pFile = ORIGFILE(pFile); + return pFile->pMethods->xUnfetch(pFile, iOfst+p->iPgOne, pPage); } /* @@ -4126,23 +4126,23 @@ static int apndUnfetch(sqlite3_file *pFile, sqlite3_int64 iOfst, void *pPage){ ** start-of-database value must be a multiple of 512. */ static sqlite3_int64 apndReadMark(sqlite3_int64 sz, sqlite3_file *pFile){ - int rc, i; - sqlite3_int64 iMark; - int msbs = 8 * (APND_MARK_FOS_SZ-1); - unsigned char a[APND_MARK_SIZE]; - - if( APND_MARK_SIZE!=(sz & 0x1ff) ) return -1; - rc = pFile->pMethods->xRead(pFile, a, APND_MARK_SIZE, sz-APND_MARK_SIZE); - if( rc ) return -1; - if( memcmp(a, APND_MARK_PREFIX, APND_MARK_PREFIX_SZ)!=0 ) return -1; - iMark = ((sqlite3_int64)(a[APND_MARK_PREFIX_SZ] & 0x7f)) << msbs; - for(i=1; i<8; i++){ - msbs -= 8; - iMark |= (sqlite3_int64)a[APND_MARK_PREFIX_SZ+i]< (sz - APND_MARK_SIZE - 512) ) return -1; - if( iMark & 0x1ff ) return -1; - return iMark; + int rc, i; + sqlite3_int64 iMark; + int msbs = 8 * (APND_MARK_FOS_SZ-1); + unsigned char a[APND_MARK_SIZE]; + + if( APND_MARK_SIZE!=(sz & 0x1ff) ) return -1; + rc = pFile->pMethods->xRead(pFile, a, APND_MARK_SIZE, sz-APND_MARK_SIZE); + if( rc ) return -1; + if( memcmp(a, APND_MARK_PREFIX, APND_MARK_PREFIX_SZ)!=0 ) return -1; + iMark = ((sqlite3_int64)(a[APND_MARK_PREFIX_SZ] & 0x7f)) << msbs; + for(i=1; i<8; i++){ + msbs -= 8; + iMark |= (sqlite3_int64)a[APND_MARK_PREFIX_SZ+i]< (sz - APND_MARK_SIZE - 512) ) return -1; + if( iMark & 0x1ff ) return -1; + return iMark; } static const char apvfsSqliteHdr[] = "SQLite format 3"; @@ -4151,24 +4151,24 @@ static const char apvfsSqliteHdr[] = "SQLite format 3"; ** Return true iff it is such. Parameter sz is the file's size. */ static int apndIsAppendvfsDatabase(sqlite3_int64 sz, sqlite3_file *pFile){ - int rc; - char zHdr[16]; - sqlite3_int64 iMark = apndReadMark(sz, pFile); - if( iMark>=0 ){ - /* If file has the correct end-marker, the expected odd size, and the + int rc; + char zHdr[16]; + sqlite3_int64 iMark = apndReadMark(sz, pFile); + if( iMark>=0 ){ + /* If file has the correct end-marker, the expected odd size, and the ** SQLite DB type marker where the end-marker puts it, then it ** is an appendvfs database. */ - rc = pFile->pMethods->xRead(pFile, zHdr, sizeof(zHdr), iMark); - if( SQLITE_OK==rc - && memcmp(zHdr, apvfsSqliteHdr, sizeof(zHdr))==0 - && (sz & 0x1ff) == APND_MARK_SIZE - && sz>=512+APND_MARK_SIZE - ){ - return 1; /* It's an appendvfs database */ - } + rc = pFile->pMethods->xRead(pFile, zHdr, sizeof(zHdr), iMark); + if( SQLITE_OK==rc + && memcmp(zHdr, apvfsSqliteHdr, sizeof(zHdr))==0 + && (sz & 0x1ff) == APND_MARK_SIZE + && sz>=512+APND_MARK_SIZE + ){ + return 1; /* It's an appendvfs database */ } - return 0; + } + return 0; } /* @@ -4176,80 +4176,80 @@ static int apndIsAppendvfsDatabase(sqlite3_int64 sz, sqlite3_file *pFile){ ** Return true iff so. Parameter sz is the file's size. */ static int apndIsOrdinaryDatabaseFile(sqlite3_int64 sz, sqlite3_file *pFile){ - char zHdr[16]; - if( apndIsAppendvfsDatabase(sz, pFile) /* rule 2 */ - || (sz & 0x1ff) != 0 - || SQLITE_OK!=pFile->pMethods->xRead(pFile, zHdr, sizeof(zHdr), 0) - || memcmp(zHdr, apvfsSqliteHdr, sizeof(zHdr))!=0 - ){ - return 0; - }else{ - return 1; - } + char zHdr[16]; + if( apndIsAppendvfsDatabase(sz, pFile) /* rule 2 */ + || (sz & 0x1ff) != 0 + || SQLITE_OK!=pFile->pMethods->xRead(pFile, zHdr, sizeof(zHdr), 0) + || memcmp(zHdr, apvfsSqliteHdr, sizeof(zHdr))!=0 + ){ + return 0; + }else{ + return 1; + } } /* ** Open an apnd file handle. */ static int apndOpen( - sqlite3_vfs *pApndVfs, - const char *zName, - sqlite3_file *pFile, - int flags, - int *pOutFlags + sqlite3_vfs *pApndVfs, + const char *zName, + sqlite3_file *pFile, + int flags, + int *pOutFlags ){ - ApndFile *pApndFile = (ApndFile*)pFile; - sqlite3_file *pBaseFile = ORIGFILE(pFile); - sqlite3_vfs *pBaseVfs = ORIGVFS(pApndVfs); - int rc; - sqlite3_int64 sz = 0; - if( (flags & SQLITE_OPEN_MAIN_DB)==0 ){ - /* The appendvfs is not to be used for transient or temporary databases. + ApndFile *pApndFile = (ApndFile*)pFile; + sqlite3_file *pBaseFile = ORIGFILE(pFile); + sqlite3_vfs *pBaseVfs = ORIGVFS(pApndVfs); + int rc; + sqlite3_int64 sz = 0; + if( (flags & SQLITE_OPEN_MAIN_DB)==0 ){ + /* The appendvfs is not to be used for transient or temporary databases. ** Just use the base VFS open to initialize the given file object and ** open the underlying file. (Appendvfs is then unused for this file.) */ - return pBaseVfs->xOpen(pBaseVfs, zName, pFile, flags, pOutFlags); - } - memset(pApndFile, 0, sizeof(ApndFile)); - pFile->pMethods = &apnd_io_methods; - pApndFile->iMark = -1; /* Append mark not yet written */ - - rc = pBaseVfs->xOpen(pBaseVfs, zName, pBaseFile, flags, pOutFlags); - if( rc==SQLITE_OK ){ - rc = pBaseFile->pMethods->xFileSize(pBaseFile, &sz); - if( rc ){ - pBaseFile->pMethods->xClose(pBaseFile); - } - } + return pBaseVfs->xOpen(pBaseVfs, zName, pFile, flags, pOutFlags); + } + memset(pApndFile, 0, sizeof(ApndFile)); + pFile->pMethods = &apnd_io_methods; + pApndFile->iMark = -1; /* Append mark not yet written */ + + rc = pBaseVfs->xOpen(pBaseVfs, zName, pBaseFile, flags, pOutFlags); + if( rc==SQLITE_OK ){ + rc = pBaseFile->pMethods->xFileSize(pBaseFile, &sz); if( rc ){ - pFile->pMethods = 0; - return rc; + pBaseFile->pMethods->xClose(pBaseFile); } - if( apndIsOrdinaryDatabaseFile(sz, pBaseFile) ){ - /* The file being opened appears to be just an ordinary DB. Copy - ** the base dispatch-table so this instance mimics the base VFS. + } + if( rc ){ + pFile->pMethods = 0; + return rc; + } + if( apndIsOrdinaryDatabaseFile(sz, pBaseFile) ){ + /* The file being opened appears to be just an ordinary DB. Copy + ** the base dispatch-table so this instance mimics the base VFS. */ - memmove(pApndFile, pBaseFile, pBaseVfs->szOsFile); - return SQLITE_OK; - } - pApndFile->iPgOne = apndReadMark(sz, pFile); - if( pApndFile->iPgOne>=0 ){ - pApndFile->iMark = sz - APND_MARK_SIZE; /* Append mark found */ - return SQLITE_OK; - } - if( (flags & SQLITE_OPEN_CREATE)==0 ){ - pBaseFile->pMethods->xClose(pBaseFile); - rc = SQLITE_CANTOPEN; - pFile->pMethods = 0; - }else{ - /* Round newly added appendvfs location to #define'd page boundary. + memmove(pApndFile, pBaseFile, pBaseVfs->szOsFile); + return SQLITE_OK; + } + pApndFile->iPgOne = apndReadMark(sz, pFile); + if( pApndFile->iPgOne>=0 ){ + pApndFile->iMark = sz - APND_MARK_SIZE; /* Append mark found */ + return SQLITE_OK; + } + if( (flags & SQLITE_OPEN_CREATE)==0 ){ + pBaseFile->pMethods->xClose(pBaseFile); + rc = SQLITE_CANTOPEN; + pFile->pMethods = 0; + }else{ + /* Round newly added appendvfs location to #define'd page boundary. ** Note that nothing has yet been written to the underlying file. ** The append mark will be written along with first content write. ** Until then, paf->iMark value indicates it is not yet written. */ - pApndFile->iPgOne = APND_START_ROUNDUP(sz); - } - return rc; + pApndFile->iPgOne = APND_START_ROUNDUP(sz); + } + return rc; } /* @@ -4259,103 +4259,103 @@ static int apndOpen( ** For now, this code deletes the underlying file too. */ static int apndDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){ - return ORIGVFS(pVfs)->xDelete(ORIGVFS(pVfs), zPath, dirSync); + return ORIGVFS(pVfs)->xDelete(ORIGVFS(pVfs), zPath, dirSync); } /* ** All other VFS methods are pass-thrus. */ static int apndAccess( - sqlite3_vfs *pVfs, - const char *zPath, - int flags, - int *pResOut + sqlite3_vfs *pVfs, + const char *zPath, + int flags, + int *pResOut ){ - return ORIGVFS(pVfs)->xAccess(ORIGVFS(pVfs), zPath, flags, pResOut); + return ORIGVFS(pVfs)->xAccess(ORIGVFS(pVfs), zPath, flags, pResOut); } static int apndFullPathname( - sqlite3_vfs *pVfs, - const char *zPath, - int nOut, - char *zOut + sqlite3_vfs *pVfs, + const char *zPath, + int nOut, + char *zOut ){ - return ORIGVFS(pVfs)->xFullPathname(ORIGVFS(pVfs),zPath,nOut,zOut); + return ORIGVFS(pVfs)->xFullPathname(ORIGVFS(pVfs),zPath,nOut,zOut); } static void *apndDlOpen(sqlite3_vfs *pVfs, const char *zPath){ - return ORIGVFS(pVfs)->xDlOpen(ORIGVFS(pVfs), zPath); + return ORIGVFS(pVfs)->xDlOpen(ORIGVFS(pVfs), zPath); } static void apndDlError(sqlite3_vfs *pVfs, int nByte, char *zErrMsg){ - ORIGVFS(pVfs)->xDlError(ORIGVFS(pVfs), nByte, zErrMsg); + ORIGVFS(pVfs)->xDlError(ORIGVFS(pVfs), nByte, zErrMsg); } static void (*apndDlSym(sqlite3_vfs *pVfs, void *p, const char *zSym))(void){ - return ORIGVFS(pVfs)->xDlSym(ORIGVFS(pVfs), p, zSym); + return ORIGVFS(pVfs)->xDlSym(ORIGVFS(pVfs), p, zSym); } static void apndDlClose(sqlite3_vfs *pVfs, void *pHandle){ - ORIGVFS(pVfs)->xDlClose(ORIGVFS(pVfs), pHandle); + ORIGVFS(pVfs)->xDlClose(ORIGVFS(pVfs), pHandle); } static int apndRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){ - return ORIGVFS(pVfs)->xRandomness(ORIGVFS(pVfs), nByte, zBufOut); + return ORIGVFS(pVfs)->xRandomness(ORIGVFS(pVfs), nByte, zBufOut); } static int apndSleep(sqlite3_vfs *pVfs, int nMicro){ - return ORIGVFS(pVfs)->xSleep(ORIGVFS(pVfs), nMicro); + return ORIGVFS(pVfs)->xSleep(ORIGVFS(pVfs), nMicro); } static int apndCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){ - return ORIGVFS(pVfs)->xCurrentTime(ORIGVFS(pVfs), pTimeOut); + return ORIGVFS(pVfs)->xCurrentTime(ORIGVFS(pVfs), pTimeOut); } static int apndGetLastError(sqlite3_vfs *pVfs, int a, char *b){ - return ORIGVFS(pVfs)->xGetLastError(ORIGVFS(pVfs), a, b); + return ORIGVFS(pVfs)->xGetLastError(ORIGVFS(pVfs), a, b); } static int apndCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *p){ - return ORIGVFS(pVfs)->xCurrentTimeInt64(ORIGVFS(pVfs), p); + return ORIGVFS(pVfs)->xCurrentTimeInt64(ORIGVFS(pVfs), p); } static int apndSetSystemCall( - sqlite3_vfs *pVfs, - const char *zName, - sqlite3_syscall_ptr pCall + sqlite3_vfs *pVfs, + const char *zName, + sqlite3_syscall_ptr pCall ){ - return ORIGVFS(pVfs)->xSetSystemCall(ORIGVFS(pVfs),zName,pCall); + return ORIGVFS(pVfs)->xSetSystemCall(ORIGVFS(pVfs),zName,pCall); } static sqlite3_syscall_ptr apndGetSystemCall( - sqlite3_vfs *pVfs, - const char *zName + sqlite3_vfs *pVfs, + const char *zName ){ - return ORIGVFS(pVfs)->xGetSystemCall(ORIGVFS(pVfs),zName); + return ORIGVFS(pVfs)->xGetSystemCall(ORIGVFS(pVfs),zName); } static const char *apndNextSystemCall(sqlite3_vfs *pVfs, const char *zName){ - return ORIGVFS(pVfs)->xNextSystemCall(ORIGVFS(pVfs), zName); + return ORIGVFS(pVfs)->xNextSystemCall(ORIGVFS(pVfs), zName); } - + #ifdef _WIN32 #endif -/* +/* ** This routine is called when the extension is loaded. ** Register the new VFS. */ int sqlite3_appendvfs_init( - sqlite3 *db, - char **pzErrMsg, - const sqlite3_api_routines *pApi + sqlite3 *db, + char **pzErrMsg, + const sqlite3_api_routines *pApi ){ - int rc = SQLITE_OK; - sqlite3_vfs *pOrig; - SQLITE_EXTENSION_INIT2(pApi); - (void)pzErrMsg; - (void)db; - pOrig = sqlite3_vfs_find(0); - if( pOrig==0 ) return SQLITE_ERROR; - apnd_vfs.iVersion = pOrig->iVersion; - apnd_vfs.pAppData = pOrig; - apnd_vfs.szOsFile = pOrig->szOsFile + sizeof(ApndFile); - rc = sqlite3_vfs_register(&apnd_vfs, 0); + int rc = SQLITE_OK; + sqlite3_vfs *pOrig; + SQLITE_EXTENSION_INIT2(pApi); + (void)pzErrMsg; + (void)db; + pOrig = sqlite3_vfs_find(0); + if( pOrig==0 ) return SQLITE_ERROR; + apnd_vfs.iVersion = pOrig->iVersion; + apnd_vfs.pAppData = pOrig; + apnd_vfs.szOsFile = pOrig->szOsFile + sizeof(ApndFile); + rc = sqlite3_vfs_register(&apnd_vfs, 0); #ifdef APPENDVFS_TEST - if( rc==SQLITE_OK ){ - rc = sqlite3_auto_extension((void(*)(void))apndvfsRegister); - } + if( rc==SQLITE_OK ){ + rc = sqlite3_auto_extension((void(*)(void))apndvfsRegister); + } #endif - if( rc==SQLITE_OK ) rc = SQLITE_OK_LOAD_PERMANENTLY; - return rc; + if( rc==SQLITE_OK ) rc = SQLITE_OK_LOAD_PERMANENTLY; + return rc; } /************************* End ../ext/misc/appendvfs.c ********************/ @@ -4393,80 +4393,80 @@ static FILE *memtraceOut; /* Methods that trace memory allocations */ static void *memtraceMalloc(int n){ - if( memtraceOut ){ - fprintf(memtraceOut, "MEMTRACE: allocate %d bytes\n", + if( memtraceOut ){ + fprintf(memtraceOut, "MEMTRACE: allocate %d bytes\n", memtraceBase.xRoundup(n)); - } - return memtraceBase.xMalloc(n); + } + return memtraceBase.xMalloc(n); } static void memtraceFree(void *p){ - if( p==0 ) return; - if( memtraceOut ){ - fprintf(memtraceOut, "MEMTRACE: free %d bytes\n", memtraceBase.xSize(p)); - } - memtraceBase.xFree(p); + if( p==0 ) return; + if( memtraceOut ){ + fprintf(memtraceOut, "MEMTRACE: free %d bytes\n", memtraceBase.xSize(p)); + } + memtraceBase.xFree(p); } static void *memtraceRealloc(void *p, int n){ - if( p==0 ) return memtraceMalloc(n); - if( n==0 ){ - memtraceFree(p); - return 0; - } - if( memtraceOut ){ - fprintf(memtraceOut, "MEMTRACE: resize %d -> %d bytes\n", + if( p==0 ) return memtraceMalloc(n); + if( n==0 ){ + memtraceFree(p); + return 0; + } + if( memtraceOut ){ + fprintf(memtraceOut, "MEMTRACE: resize %d -> %d bytes\n", memtraceBase.xSize(p), memtraceBase.xRoundup(n)); - } - return memtraceBase.xRealloc(p, n); + } + return memtraceBase.xRealloc(p, n); } static int memtraceSize(void *p){ - return memtraceBase.xSize(p); + return memtraceBase.xSize(p); } static int memtraceRoundup(int n){ - return memtraceBase.xRoundup(n); + return memtraceBase.xRoundup(n); } static int memtraceInit(void *p){ - return memtraceBase.xInit(p); + return memtraceBase.xInit(p); } static void memtraceShutdown(void *p){ - memtraceBase.xShutdown(p); + memtraceBase.xShutdown(p); } /* The substitute memory allocator */ static sqlite3_mem_methods ersaztMethods = { - memtraceMalloc, - memtraceFree, - memtraceRealloc, - memtraceSize, - memtraceRoundup, - memtraceInit, - memtraceShutdown, - 0 + memtraceMalloc, + memtraceFree, + memtraceRealloc, + memtraceSize, + memtraceRoundup, + memtraceInit, + memtraceShutdown, + 0 }; /* Begin tracing memory allocations to out. */ int sqlite3MemTraceActivate(FILE *out){ - int rc = SQLITE_OK; - if( memtraceBase.xMalloc==0 ){ - rc = sqlite3_config(SQLITE_CONFIG_GETMALLOC, &memtraceBase); - if( rc==SQLITE_OK ){ - rc = sqlite3_config(SQLITE_CONFIG_MALLOC, &ersaztMethods); - } + int rc = SQLITE_OK; + if( memtraceBase.xMalloc==0 ){ + rc = sqlite3_config(SQLITE_CONFIG_GETMALLOC, &memtraceBase); + if( rc==SQLITE_OK ){ + rc = sqlite3_config(SQLITE_CONFIG_MALLOC, &ersaztMethods); } - memtraceOut = out; - return rc; + } + memtraceOut = out; + return rc; } /* Deactivate memory tracing */ int sqlite3MemTraceDeactivate(void){ - int rc = SQLITE_OK; - if( memtraceBase.xMalloc!=0 ){ - rc = sqlite3_config(SQLITE_CONFIG_MALLOC, &memtraceBase); - if( rc==SQLITE_OK ){ - memset(&memtraceBase, 0, sizeof(memtraceBase)); - } + int rc = SQLITE_OK; + if( memtraceBase.xMalloc!=0 ){ + rc = sqlite3_config(SQLITE_CONFIG_MALLOC, &memtraceBase); + if( rc==SQLITE_OK ){ + memset(&memtraceBase, 0, sizeof(memtraceBase)); } - memtraceOut = 0; - return rc; + } + memtraceOut = 0; + return rc; } /************************* End ../ext/misc/memtrace.c ********************/ @@ -4511,57 +4511,57 @@ SQLITE_EXTENSION_INIT1 ** compare in numeric order. */ static int uintCollFunc( - void *notUsed, - int nKey1, const void *pKey1, - int nKey2, const void *pKey2 + void *notUsed, + int nKey1, const void *pKey1, + int nKey2, const void *pKey2 ){ - const unsigned char *zA = (const unsigned char*)pKey1; - const unsigned char *zB = (const unsigned char*)pKey2; - int i=0, j=0, x; - (void)notUsed; - while( ia); + sqlite3_free(p->a); } /* ** Destroy a Decimal object */ static void decimal_free(Decimal *p){ - if( p ){ - decimal_clear(p); - sqlite3_free(p); - } + if( p ){ + decimal_clear(p); + sqlite3_free(p); + } } /* @@ -4630,172 +4630,172 @@ static void decimal_free(Decimal *p){ ** by the input string. */ static Decimal *decimal_new( - sqlite3_context *pCtx, - sqlite3_value *pIn, - int nAlt, - const unsigned char *zAlt + sqlite3_context *pCtx, + sqlite3_value *pIn, + int nAlt, + const unsigned char *zAlt ){ - Decimal *p; - int n, i; - const unsigned char *zIn; - int iExp = 0; - p = sqlite3_malloc( sizeof(*p) ); - if( p==0 ) goto new_no_mem; - p->sign = 0; - p->oom = 0; - p->isInit = 1; - p->isNull = 0; - p->nDigit = 0; - p->nFrac = 0; - if( zAlt ){ - n = nAlt, - zIn = zAlt; - }else{ - if( sqlite3_value_type(pIn)==SQLITE_NULL ){ - p->a = 0; - p->isNull = 1; - return p; - } - n = sqlite3_value_bytes(pIn); - zIn = sqlite3_value_text(pIn); - } - p->a = sqlite3_malloc64( n+1 ); - if( p->a==0 ) goto new_no_mem; - for(i=0; isspace(zIn[i]); i++){} - if( zIn[i]=='-' ){ - p->sign = 1; - i++; - }else if( zIn[i]=='+' ){ - i++; - } - while( i='0' && c<='9' ){ - p->a[p->nDigit++] = c - '0'; - }else if( c=='.' ){ - p->nFrac = p->nDigit + 1; - }else if( c=='e' || c=='E' ){ - int j = i+1; - int neg = 0; - if( j>=n ) break; - if( zIn[j]=='-' ){ - neg = 1; - j++; - }else if( zIn[j]=='+' ){ - j++; - } - while( j='0' && zIn[j]<='9' ){ - iExp = iExp*10 + zIn[j] - '0'; - } - j++; - } - if( neg ) iExp = -iExp; - break; + Decimal *p; + int n, i; + const unsigned char *zIn; + int iExp = 0; + p = sqlite3_malloc( sizeof(*p) ); + if( p==0 ) goto new_no_mem; + p->sign = 0; + p->oom = 0; + p->isInit = 1; + p->isNull = 0; + p->nDigit = 0; + p->nFrac = 0; + if( zAlt ){ + n = nAlt, + zIn = zAlt; + }else{ + if( sqlite3_value_type(pIn)==SQLITE_NULL ){ + p->a = 0; + p->isNull = 1; + return p; + } + n = sqlite3_value_bytes(pIn); + zIn = sqlite3_value_text(pIn); + } + p->a = sqlite3_malloc64( n+1 ); + if( p->a==0 ) goto new_no_mem; + for(i=0; isspace(zIn[i]); i++){} + if( zIn[i]=='-' ){ + p->sign = 1; + i++; + }else if( zIn[i]=='+' ){ + i++; + } + while( i='0' && c<='9' ){ + p->a[p->nDigit++] = c - '0'; + }else if( c=='.' ){ + p->nFrac = p->nDigit + 1; + }else if( c=='e' || c=='E' ){ + int j = i+1; + int neg = 0; + if( j>=n ) break; + if( zIn[j]=='-' ){ + neg = 1; + j++; + }else if( zIn[j]=='+' ){ + j++; + } + while( j='0' && zIn[j]<='9' ){ + iExp = iExp*10 + zIn[j] - '0'; } - i++; - } - if( p->nFrac ){ - p->nFrac = p->nDigit - (p->nFrac - 1); + j++; + } + if( neg ) iExp = -iExp; + break; + } + i++; + } + if( p->nFrac ){ + p->nFrac = p->nDigit - (p->nFrac - 1); + } + if( iExp>0 ){ + if( p->nFrac>0 ){ + if( iExp<=p->nFrac ){ + p->nFrac -= iExp; + iExp = 0; + }else{ + iExp -= p->nFrac; + p->nFrac = 0; + } + } + if( iExp>0 ){ + p->a = sqlite3_realloc64(p->a, p->nDigit + iExp + 1 ); + if( p->a==0 ) goto new_no_mem; + memset(p->a+p->nDigit, 0, iExp); + p->nDigit += iExp; + } + }else if( iExp<0 ){ + int nExtra; + iExp = -iExp; + nExtra = p->nDigit - p->nFrac - 1; + if( nExtra ){ + if( nExtra>=iExp ){ + p->nFrac += iExp; + iExp = 0; + }else{ + iExp -= nExtra; + p->nFrac = p->nDigit - 1; + } } if( iExp>0 ){ - if( p->nFrac>0 ){ - if( iExp<=p->nFrac ){ - p->nFrac -= iExp; - iExp = 0; - }else{ - iExp -= p->nFrac; - p->nFrac = 0; - } - } - if( iExp>0 ){ - p->a = sqlite3_realloc64(p->a, p->nDigit + iExp + 1 ); - if( p->a==0 ) goto new_no_mem; - memset(p->a+p->nDigit, 0, iExp); - p->nDigit += iExp; - } - }else if( iExp<0 ){ - int nExtra; - iExp = -iExp; - nExtra = p->nDigit - p->nFrac - 1; - if( nExtra ){ - if( nExtra>=iExp ){ - p->nFrac += iExp; - iExp = 0; - }else{ - iExp -= nExtra; - p->nFrac = p->nDigit - 1; - } - } - if( iExp>0 ){ - p->a = sqlite3_realloc64(p->a, p->nDigit + iExp + 1 ); - if( p->a==0 ) goto new_no_mem; - memmove(p->a+iExp, p->a, p->nDigit); - memset(p->a, 0, iExp); - p->nDigit += iExp; - p->nFrac += iExp; - } + p->a = sqlite3_realloc64(p->a, p->nDigit + iExp + 1 ); + if( p->a==0 ) goto new_no_mem; + memmove(p->a+iExp, p->a, p->nDigit); + memset(p->a, 0, iExp); + p->nDigit += iExp; + p->nFrac += iExp; } - return p; + } + return p; new_no_mem: - if( pCtx ) sqlite3_result_error_nomem(pCtx); - sqlite3_free(p); - return 0; + if( pCtx ) sqlite3_result_error_nomem(pCtx); + sqlite3_free(p); + return 0; } /* ** Make the given Decimal the result. */ static void decimal_result(sqlite3_context *pCtx, Decimal *p){ - char *z; - int i, j; - int n; - if( p==0 || p->oom ){ - sqlite3_result_error_nomem(pCtx); - return; - } - if( p->isNull ){ - sqlite3_result_null(pCtx); - return; - } - z = sqlite3_malloc( p->nDigit+4 ); - if( z==0 ){ - sqlite3_result_error_nomem(pCtx); - return; - } - i = 0; - if( p->nDigit==0 || (p->nDigit==1 && p->a[0]==0) ){ - p->sign = 0; - } - if( p->sign ){ - z[0] = '-'; - i = 1; - } - n = p->nDigit - p->nFrac; - if( n<=0 ){ - z[i++] = '0'; - } - j = 0; - while( n>1 && p->a[j]==0 ){ - j++; - n--; - } - while( n>0 ){ - z[i++] = p->a[j] + '0'; - j++; - n--; - } - if( p->nFrac ){ - z[i++] = '.'; - do{ - z[i++] = p->a[j] + '0'; - j++; - }while( jnDigit ); - } - z[i] = 0; - sqlite3_result_text(pCtx, z, i, sqlite3_free); + char *z; + int i, j; + int n; + if( p==0 || p->oom ){ + sqlite3_result_error_nomem(pCtx); + return; + } + if( p->isNull ){ + sqlite3_result_null(pCtx); + return; + } + z = sqlite3_malloc( p->nDigit+4 ); + if( z==0 ){ + sqlite3_result_error_nomem(pCtx); + return; + } + i = 0; + if( p->nDigit==0 || (p->nDigit==1 && p->a[0]==0) ){ + p->sign = 0; + } + if( p->sign ){ + z[0] = '-'; + i = 1; + } + n = p->nDigit - p->nFrac; + if( n<=0 ){ + z[i++] = '0'; + } + j = 0; + while( n>1 && p->a[j]==0 ){ + j++; + n--; + } + while( n>0 ){ + z[i++] = p->a[j] + '0'; + j++; + n--; + } + if( p->nFrac ){ + z[i++] = '.'; + do{ + z[i++] = p->a[j] + '0'; + j++; + }while( jnDigit ); + } + z[i] = 0; + sqlite3_result_text(pCtx, z, i, sqlite3_free); } /* @@ -4804,14 +4804,14 @@ static void decimal_result(sqlite3_context *pCtx, Decimal *p){ ** Convert input X into decimal and then back into text */ static void decimalFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv + sqlite3_context *context, + int argc, + sqlite3_value **argv ){ - Decimal *p = decimal_new(context, argv[0], 0, 0); - UNUSED_PARAMETER(argc); - decimal_result(context, p); - decimal_free(p); + Decimal *p = decimal_new(context, argv[0], 0, 0); + UNUSED_PARAMETER(argc); + decimal_result(context, p); + decimal_free(p); } /* @@ -4826,27 +4826,27 @@ static void decimalFunc( ** pB->isNull==0 */ static int decimal_cmp(const Decimal *pA, const Decimal *pB){ - int nASig, nBSig, rc, n; - if( pA->sign!=pB->sign ){ - return pA->sign ? -1 : +1; - } - if( pA->sign ){ - const Decimal *pTemp = pA; - pA = pB; - pB = pTemp; - } - nASig = pA->nDigit - pA->nFrac; - nBSig = pB->nDigit - pB->nFrac; - if( nASig!=nBSig ){ - return nASig - nBSig; - } - n = pA->nDigit; - if( n>pB->nDigit ) n = pB->nDigit; - rc = memcmp(pA->a, pB->a, n); - if( rc==0 ){ - rc = pA->nDigit - pB->nDigit; - } - return rc; + int nASig, nBSig, rc, n; + if( pA->sign!=pB->sign ){ + return pA->sign ? -1 : +1; + } + if( pA->sign ){ + const Decimal *pTemp = pA; + pA = pB; + pB = pTemp; + } + nASig = pA->nDigit - pA->nFrac; + nBSig = pB->nDigit - pB->nFrac; + if( nASig!=nBSig ){ + return nASig - nBSig; + } + n = pA->nDigit; + if( n>pB->nDigit ) n = pB->nDigit; + rc = memcmp(pA->a, pB->a, n); + if( rc==0 ){ + rc = pA->nDigit - pB->nDigit; + } + return rc; } /* @@ -4856,25 +4856,25 @@ static int decimal_cmp(const Decimal *pA, const Decimal *pB){ ** greater than Y. */ static void decimalCmpFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv + sqlite3_context *context, + int argc, + sqlite3_value **argv ){ - Decimal *pA = 0, *pB = 0; - int rc; - - UNUSED_PARAMETER(argc); - pA = decimal_new(context, argv[0], 0, 0); - if( pA==0 || pA->isNull ) goto cmp_done; - pB = decimal_new(context, argv[1], 0, 0); - if( pB==0 || pB->isNull ) goto cmp_done; - rc = decimal_cmp(pA, pB); - if( rc<0 ) rc = -1; - else if( rc>0 ) rc = +1; - sqlite3_result_int(context, rc); + Decimal *pA = 0, *pB = 0; + int rc; + + UNUSED_PARAMETER(argc); + pA = decimal_new(context, argv[0], 0, 0); + if( pA==0 || pA->isNull ) goto cmp_done; + pB = decimal_new(context, argv[1], 0, 0); + if( pB==0 || pB->isNull ) goto cmp_done; + rc = decimal_cmp(pA, pB); + if( rc<0 ) rc = -1; + else if( rc>0 ) rc = +1; + sqlite3_result_int(context, rc); cmp_done: - decimal_free(pA); - decimal_free(pB); + decimal_free(pA); + decimal_free(pB); } /* @@ -4882,27 +4882,27 @@ cmp_done: ** digits to the right of the decimal point. */ static void decimal_expand(Decimal *p, int nDigit, int nFrac){ - int nAddSig; - int nAddFrac; - if( p==0 ) return; - nAddFrac = nFrac - p->nFrac; - nAddSig = (nDigit - p->nDigit) - nAddFrac; - if( nAddFrac==0 && nAddSig==0 ) return; - p->a = sqlite3_realloc64(p->a, nDigit+1); - if( p->a==0 ){ - p->oom = 1; - return; - } - if( nAddSig ){ - memmove(p->a+nAddSig, p->a, p->nDigit); - memset(p->a, 0, nAddSig); - p->nDigit += nAddSig; - } - if( nAddFrac ){ - memset(p->a+p->nDigit, 0, nAddFrac); - p->nDigit += nAddFrac; - p->nFrac += nAddFrac; - } + int nAddSig; + int nAddFrac; + if( p==0 ) return; + nAddFrac = nFrac - p->nFrac; + nAddSig = (nDigit - p->nDigit) - nAddFrac; + if( nAddFrac==0 && nAddSig==0 ) return; + p->a = sqlite3_realloc64(p->a, nDigit+1); + if( p->a==0 ){ + p->oom = 1; + return; + } + if( nAddSig ){ + memmove(p->a+nAddSig, p->a, p->nDigit); + memset(p->a, 0, nAddSig); + p->nDigit += nAddSig; + } + if( nAddFrac ){ + memset(p->a+p->nDigit, 0, nAddFrac); + p->nDigit += nAddFrac; + p->nFrac += nAddFrac; + } } /* @@ -4911,92 +4911,92 @@ static void decimal_expand(Decimal *p, int nDigit, int nFrac){ ** Both pA and pB might become denormalized by this routine. */ static void decimal_add(Decimal *pA, Decimal *pB){ - int nSig, nFrac, nDigit; - int i, rc; - if( pA==0 ){ - return; - } - if( pA->oom || pB==0 || pB->oom ){ - pA->oom = 1; - return; - } - if( pA->isNull || pB->isNull ){ - pA->isNull = 1; - return; - } - nSig = pA->nDigit - pA->nFrac; - if( nSig && pA->a[0]==0 ) nSig--; - if( nSignDigit-pB->nFrac ){ - nSig = pB->nDigit - pB->nFrac; - } - nFrac = pA->nFrac; - if( nFracnFrac ) nFrac = pB->nFrac; - nDigit = nSig + nFrac + 1; - decimal_expand(pA, nDigit, nFrac); - decimal_expand(pB, nDigit, nFrac); - if( pA->oom || pB->oom ){ - pA->oom = 1; + int nSig, nFrac, nDigit; + int i, rc; + if( pA==0 ){ + return; + } + if( pA->oom || pB==0 || pB->oom ){ + pA->oom = 1; + return; + } + if( pA->isNull || pB->isNull ){ + pA->isNull = 1; + return; + } + nSig = pA->nDigit - pA->nFrac; + if( nSig && pA->a[0]==0 ) nSig--; + if( nSignDigit-pB->nFrac ){ + nSig = pB->nDigit - pB->nFrac; + } + nFrac = pA->nFrac; + if( nFracnFrac ) nFrac = pB->nFrac; + nDigit = nSig + nFrac + 1; + decimal_expand(pA, nDigit, nFrac); + decimal_expand(pB, nDigit, nFrac); + if( pA->oom || pB->oom ){ + pA->oom = 1; + }else{ + if( pA->sign==pB->sign ){ + int carry = 0; + for(i=nDigit-1; i>=0; i--){ + int x = pA->a[i] + pB->a[i] + carry; + if( x>=10 ){ + carry = 1; + pA->a[i] = x - 10; + }else{ + carry = 0; + pA->a[i] = x; + } + } }else{ - if( pA->sign==pB->sign ){ - int carry = 0; - for(i=nDigit-1; i>=0; i--){ - int x = pA->a[i] + pB->a[i] + carry; - if( x>=10 ){ - carry = 1; - pA->a[i] = x - 10; - }else{ - carry = 0; - pA->a[i] = x; - } - } + signed char *aA, *aB; + int borrow = 0; + rc = memcmp(pA->a, pB->a, nDigit); + if( rc<0 ){ + aA = pB->a; + aB = pA->a; + pA->sign = !pA->sign; + }else{ + aA = pA->a; + aB = pB->a; + } + for(i=nDigit-1; i>=0; i--){ + int x = aA[i] - aB[i] - borrow; + if( x<0 ){ + pA->a[i] = x+10; + borrow = 1; }else{ - signed char *aA, *aB; - int borrow = 0; - rc = memcmp(pA->a, pB->a, nDigit); - if( rc<0 ){ - aA = pB->a; - aB = pA->a; - pA->sign = !pA->sign; - }else{ - aA = pA->a; - aB = pB->a; - } - for(i=nDigit-1; i>=0; i--){ - int x = aA[i] - aB[i] - borrow; - if( x<0 ){ - pA->a[i] = x+10; - borrow = 1; - }else{ - pA->a[i] = x; - borrow = 0; - } - } + pA->a[i] = x; + borrow = 0; } + } } + } } /* ** Compare text in decimal order. */ static int decimalCollFunc( - void *notUsed, - int nKey1, const void *pKey1, - int nKey2, const void *pKey2 + void *notUsed, + int nKey1, const void *pKey1, + int nKey2, const void *pKey2 ){ - const unsigned char *zA = (const unsigned char*)pKey1; - const unsigned char *zB = (const unsigned char*)pKey2; - Decimal *pA = decimal_new(0, 0, nKey1, zA); - Decimal *pB = decimal_new(0, 0, nKey2, zB); - int rc; - UNUSED_PARAMETER(notUsed); - if( pA==0 || pB==0 ){ - rc = 0; - }else{ - rc = decimal_cmp(pA, pB); - } - decimal_free(pA); - decimal_free(pB); - return rc; + const unsigned char *zA = (const unsigned char*)pKey1; + const unsigned char *zB = (const unsigned char*)pKey2; + Decimal *pA = decimal_new(0, 0, nKey1, zA); + Decimal *pB = decimal_new(0, 0, nKey2, zB); + int rc; + UNUSED_PARAMETER(notUsed); + if( pA==0 || pB==0 ){ + rc = 0; + }else{ + rc = decimal_cmp(pA, pB); + } + decimal_free(pA); + decimal_free(pB); + return rc; } @@ -5007,33 +5007,33 @@ static int decimalCollFunc( ** Return the sum or difference of X and Y. */ static void decimalAddFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv + sqlite3_context *context, + int argc, + sqlite3_value **argv ){ - Decimal *pA = decimal_new(context, argv[0], 0, 0); - Decimal *pB = decimal_new(context, argv[1], 0, 0); - UNUSED_PARAMETER(argc); - decimal_add(pA, pB); - decimal_result(context, pA); - decimal_free(pA); - decimal_free(pB); + Decimal *pA = decimal_new(context, argv[0], 0, 0); + Decimal *pB = decimal_new(context, argv[1], 0, 0); + UNUSED_PARAMETER(argc); + decimal_add(pA, pB); + decimal_result(context, pA); + decimal_free(pA); + decimal_free(pB); } static void decimalSubFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv + sqlite3_context *context, + int argc, + sqlite3_value **argv ){ - Decimal *pA = decimal_new(context, argv[0], 0, 0); - Decimal *pB = decimal_new(context, argv[1], 0, 0); - UNUSED_PARAMETER(argc); - if( pB ){ - pB->sign = !pB->sign; - decimal_add(pA, pB); - decimal_result(context, pA); - } - decimal_free(pA); - decimal_free(pB); + Decimal *pA = decimal_new(context, argv[0], 0, 0); + Decimal *pB = decimal_new(context, argv[1], 0, 0); + UNUSED_PARAMETER(argc); + if( pB ){ + pB->sign = !pB->sign; + decimal_add(pA, pB); + decimal_result(context, pA); + } + decimal_free(pA); + decimal_free(pB); } /* Aggregate funcion: decimal_sum(X) @@ -5042,57 +5042,57 @@ static void decimalSubFunc( ** precision. */ static void decimalSumStep( - sqlite3_context *context, - int argc, - sqlite3_value **argv + sqlite3_context *context, + int argc, + sqlite3_value **argv ){ - Decimal *p; - Decimal *pArg; - UNUSED_PARAMETER(argc); - p = sqlite3_aggregate_context(context, sizeof(*p)); - if( p==0 ) return; - if( !p->isInit ){ - p->isInit = 1; - p->a = sqlite3_malloc(2); - if( p->a==0 ){ - p->oom = 1; - }else{ - p->a[0] = 0; - } - p->nDigit = 1; - p->nFrac = 0; + Decimal *p; + Decimal *pArg; + UNUSED_PARAMETER(argc); + p = sqlite3_aggregate_context(context, sizeof(*p)); + if( p==0 ) return; + if( !p->isInit ){ + p->isInit = 1; + p->a = sqlite3_malloc(2); + if( p->a==0 ){ + p->oom = 1; + }else{ + p->a[0] = 0; } - if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return; - pArg = decimal_new(context, argv[0], 0, 0); - decimal_add(p, pArg); - decimal_free(pArg); + p->nDigit = 1; + p->nFrac = 0; + } + if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return; + pArg = decimal_new(context, argv[0], 0, 0); + decimal_add(p, pArg); + decimal_free(pArg); } static void decimalSumInverse( - sqlite3_context *context, - int argc, - sqlite3_value **argv + sqlite3_context *context, + int argc, + sqlite3_value **argv ){ - Decimal *p; - Decimal *pArg; - UNUSED_PARAMETER(argc); - p = sqlite3_aggregate_context(context, sizeof(*p)); - if( p==0 ) return; - if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return; - pArg = decimal_new(context, argv[0], 0, 0); - if( pArg ) pArg->sign = !pArg->sign; - decimal_add(p, pArg); - decimal_free(pArg); + Decimal *p; + Decimal *pArg; + UNUSED_PARAMETER(argc); + p = sqlite3_aggregate_context(context, sizeof(*p)); + if( p==0 ) return; + if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return; + pArg = decimal_new(context, argv[0], 0, 0); + if( pArg ) pArg->sign = !pArg->sign; + decimal_add(p, pArg); + decimal_free(pArg); } static void decimalSumValue(sqlite3_context *context){ - Decimal *p = sqlite3_aggregate_context(context, 0); - if( p==0 ) return; - decimal_result(context, p); + Decimal *p = sqlite3_aggregate_context(context, 0); + if( p==0 ) return; + decimal_result(context, p); } static void decimalSumFinalize(sqlite3_context *context){ - Decimal *p = sqlite3_aggregate_context(context, 0); - if( p==0 ) return; - decimal_result(context, p); - decimal_clear(p); + Decimal *p = sqlite3_aggregate_context(context, 0); + if( p==0 ) return; + decimal_result(context, p); + decimal_clear(p); } /* @@ -5106,100 +5106,100 @@ static void decimalSumFinalize(sqlite3_context *context){ ** either the number of digits in either input. */ static void decimalMulFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv + sqlite3_context *context, + int argc, + sqlite3_value **argv ){ - Decimal *pA = decimal_new(context, argv[0], 0, 0); - Decimal *pB = decimal_new(context, argv[1], 0, 0); - signed char *acc = 0; - int i, j, k; - int minFrac; - UNUSED_PARAMETER(argc); - if( pA==0 || pA->oom || pA->isNull - || pB==0 || pB->oom || pB->isNull - ){ - goto mul_end; - } - acc = sqlite3_malloc64( pA->nDigit + pB->nDigit + 2 ); - if( acc==0 ){ - sqlite3_result_error_nomem(context); - goto mul_end; - } - memset(acc, 0, pA->nDigit + pB->nDigit + 2); - minFrac = pA->nFrac; - if( pB->nFracnFrac; - for(i=pA->nDigit-1; i>=0; i--){ - signed char f = pA->a[i]; - int carry = 0, x; - for(j=pB->nDigit-1, k=i+j+3; j>=0; j--, k--){ - x = acc[k] + f*pB->a[j] + carry; - acc[k] = x%10; - carry = x/10; - } - x = acc[k] + carry; - acc[k] = x%10; - acc[k-1] += x/10; - } - sqlite3_free(pA->a); - pA->a = acc; - acc = 0; - pA->nDigit += pB->nDigit + 2; - pA->nFrac += pB->nFrac; - pA->sign ^= pB->sign; - while( pA->nFrac>minFrac && pA->a[pA->nDigit-1]==0 ){ - pA->nFrac--; - pA->nDigit--; - } - decimal_result(context, pA); + Decimal *pA = decimal_new(context, argv[0], 0, 0); + Decimal *pB = decimal_new(context, argv[1], 0, 0); + signed char *acc = 0; + int i, j, k; + int minFrac; + UNUSED_PARAMETER(argc); + if( pA==0 || pA->oom || pA->isNull + || pB==0 || pB->oom || pB->isNull + ){ + goto mul_end; + } + acc = sqlite3_malloc64( pA->nDigit + pB->nDigit + 2 ); + if( acc==0 ){ + sqlite3_result_error_nomem(context); + goto mul_end; + } + memset(acc, 0, pA->nDigit + pB->nDigit + 2); + minFrac = pA->nFrac; + if( pB->nFracnFrac; + for(i=pA->nDigit-1; i>=0; i--){ + signed char f = pA->a[i]; + int carry = 0, x; + for(j=pB->nDigit-1, k=i+j+3; j>=0; j--, k--){ + x = acc[k] + f*pB->a[j] + carry; + acc[k] = x%10; + carry = x/10; + } + x = acc[k] + carry; + acc[k] = x%10; + acc[k-1] += x/10; + } + sqlite3_free(pA->a); + pA->a = acc; + acc = 0; + pA->nDigit += pB->nDigit + 2; + pA->nFrac += pB->nFrac; + pA->sign ^= pB->sign; + while( pA->nFrac>minFrac && pA->a[pA->nDigit-1]==0 ){ + pA->nFrac--; + pA->nDigit--; + } + decimal_result(context, pA); mul_end: - sqlite3_free(acc); - decimal_free(pA); - decimal_free(pB); + sqlite3_free(acc); + decimal_free(pA); + decimal_free(pB); } #ifdef _WIN32 #endif int sqlite3_decimal_init( - sqlite3 *db, - char **pzErrMsg, - const sqlite3_api_routines *pApi + sqlite3 *db, + char **pzErrMsg, + const sqlite3_api_routines *pApi ){ - int rc = SQLITE_OK; - static const struct { - const char *zFuncName; - int nArg; - void (*xFunc)(sqlite3_context*,int,sqlite3_value**); - } aFunc[] = { - { "decimal", 1, decimalFunc }, - { "decimal_cmp", 2, decimalCmpFunc }, - { "decimal_add", 2, decimalAddFunc }, - { "decimal_sub", 2, decimalSubFunc }, - { "decimal_mul", 2, decimalMulFunc }, - }; - unsigned int i; - (void)pzErrMsg; /* Unused parameter */ - - SQLITE_EXTENSION_INIT2(pApi); - - for(i=0; i>52; - m = a & ((((sqlite3_int64)1)<<52)-1); - if( e==0 ){ - m <<= 1; - }else{ - m |= ((sqlite3_int64)1)<<52; - } - while( e<1075 && m>0 && (m&1)==0 ){ - m >>= 1; - e++; - } - if( isNeg ) m = -m; - } - switch( *(int*)sqlite3_user_data(context) ){ - case 0: - sqlite3_snprintf(sizeof(zResult), zResult, "ieee754(%lld,%d)", - m, e-1075); - sqlite3_result_text(context, zResult, -1, SQLITE_TRANSIENT); - break; - case 1: - sqlite3_result_int64(context, m); - break; - case 2: - sqlite3_result_int(context, e-1075); - break; - } + if( argc==1 ){ + sqlite3_int64 m, a; + double r; + int e; + int isNeg; + char zResult[100]; + assert( sizeof(m)==sizeof(r) ); + if( sqlite3_value_type(argv[0])==SQLITE_BLOB + && sqlite3_value_bytes(argv[0])==sizeof(r) + ){ + const unsigned char *x = sqlite3_value_blob(argv[0]); + unsigned int i; + sqlite3_uint64 v = 0; + for(i=0; i10000 ){ - e = 10000; - }else if( e<-10000 ){ - e = -10000; - } - - if( m<0 ){ - isNeg = 1; - m = -m; - if( m<0 ) return; - }else if( m==0 && e>-1000 && e<1000 ){ - sqlite3_result_double(context, 0.0); - return; - } - while( (m>>32)&0xffe00000 ){ - m >>= 1; - e++; - } - while( m!=0 && ((m>>32)&0xfff00000)==0 ){ - m <<= 1; - e--; - } - e += 1075; - if( e<=0 ){ - /* Subnormal */ - if( 1-e >= 64 ){ - m = 0; - }else{ - m >>= 1-e; - } - e = 0; - }else if( e>0x7ff ){ - e = 0x7ff; - } - a = m & ((((sqlite3_int64)1)<<52)-1); - a |= e<<52; - if( isNeg ) a |= ((sqlite3_uint64)1)<<63; - memcpy(&r, &a, sizeof(r)); - sqlite3_result_double(context, r); + r = sqlite3_value_double(argv[0]); + } + if( r<0.0 ){ + isNeg = 1; + r = -r; + }else{ + isNeg = 0; } + memcpy(&a,&r,sizeof(a)); + if( a==0 ){ + e = 0; + m = 0; + }else{ + e = a>>52; + m = a & ((((sqlite3_int64)1)<<52)-1); + if( e==0 ){ + m <<= 1; + }else{ + m |= ((sqlite3_int64)1)<<52; + } + while( e<1075 && m>0 && (m&1)==0 ){ + m >>= 1; + e++; + } + if( isNeg ) m = -m; + } + switch( *(int*)sqlite3_user_data(context) ){ + case 0: + sqlite3_snprintf(sizeof(zResult), zResult, "ieee754(%lld,%d)", + m, e-1075); + sqlite3_result_text(context, zResult, -1, SQLITE_TRANSIENT); + break; + case 1: + sqlite3_result_int64(context, m); + break; + case 2: + sqlite3_result_int(context, e-1075); + break; + } + }else{ + sqlite3_int64 m, e, a; + double r; + int isNeg = 0; + m = sqlite3_value_int64(argv[0]); + e = sqlite3_value_int64(argv[1]); + + /* Limit the range of e. Ticket 22dea1cfdb9151e4 2021-03-02 */ + if( e>10000 ){ + e = 10000; + }else if( e<-10000 ){ + e = -10000; + } + + if( m<0 ){ + isNeg = 1; + m = -m; + if( m<0 ) return; + }else if( m==0 && e>-1000 && e<1000 ){ + sqlite3_result_double(context, 0.0); + return; + } + while( (m>>32)&0xffe00000 ){ + m >>= 1; + e++; + } + while( m!=0 && ((m>>32)&0xfff00000)==0 ){ + m <<= 1; + e--; + } + e += 1075; + if( e<=0 ){ + /* Subnormal */ + if( 1-e >= 64 ){ + m = 0; + }else{ + m >>= 1-e; + } + e = 0; + }else if( e>0x7ff ){ + e = 0x7ff; + } + a = m & ((((sqlite3_int64)1)<<52)-1); + a |= e<<52; + if( isNeg ) a |= ((sqlite3_uint64)1)<<63; + memcpy(&r, &a, sizeof(r)); + sqlite3_result_double(context, r); + } } /* ** Functions to convert between blobs and floats. */ static void ieee754func_from_blob( - sqlite3_context *context, - int argc, - sqlite3_value **argv + sqlite3_context *context, + int argc, + sqlite3_value **argv ){ - UNUSED_PARAMETER(argc); - if( sqlite3_value_type(argv[0])==SQLITE_BLOB - && sqlite3_value_bytes(argv[0])==sizeof(double) - ){ - double r; - const unsigned char *x = sqlite3_value_blob(argv[0]); - unsigned int i; - sqlite3_uint64 v = 0; - for(i=0; i>= 8; - } - sqlite3_result_blob(context, a, sizeof(r), SQLITE_TRANSIENT); + UNUSED_PARAMETER(argc); + if( sqlite3_value_type(argv[0])==SQLITE_FLOAT + || sqlite3_value_type(argv[0])==SQLITE_INTEGER + ){ + double r = sqlite3_value_double(argv[0]); + sqlite3_uint64 v; + unsigned char a[sizeof(r)]; + unsigned int i; + memcpy(&v, &r, sizeof(r)); + for(i=1; i<=sizeof(r); i++){ + a[sizeof(r)-i] = v&0xff; + v >>= 8; } + sqlite3_result_blob(context, a, sizeof(r), SQLITE_TRANSIENT); + } } @@ -5467,35 +5467,35 @@ static void ieee754func_to_blob( #endif int sqlite3_ieee_init( - sqlite3 *db, - char **pzErrMsg, - const sqlite3_api_routines *pApi + sqlite3 *db, + char **pzErrMsg, + const sqlite3_api_routines *pApi ){ - static const struct { - char *zFName; - int nArg; - int iAux; - void (*xFunc)(sqlite3_context*,int,sqlite3_value**); - } aFunc[] = { - { "ieee754", 1, 0, ieee754func }, - { "ieee754", 2, 0, ieee754func }, - { "ieee754_mantissa", 1, 1, ieee754func }, - { "ieee754_exponent", 1, 2, ieee754func }, - { "ieee754_to_blob", 1, 0, ieee754func_to_blob }, - { "ieee754_from_blob", 1, 0, ieee754func_from_blob }, - - }; - unsigned int i; - int rc = SQLITE_OK; - SQLITE_EXTENSION_INIT2(pApi); - (void)pzErrMsg; /* Unused parameter */ - for(i=0; ibase; - return SQLITE_OK; + series_cursor *pCur; + (void)pUnused; + pCur = sqlite3_malloc( sizeof(*pCur) ); + if( pCur==0 ) return SQLITE_NOMEM; + memset(pCur, 0, sizeof(*pCur)); + *ppCursor = &pCur->base; + return SQLITE_OK; } /* ** Destructor for a series_cursor. */ static int seriesClose(sqlite3_vtab_cursor *cur){ - sqlite3_free(cur); - return SQLITE_OK; + sqlite3_free(cur); + return SQLITE_OK; } @@ -5671,14 +5671,14 @@ static int seriesClose(sqlite3_vtab_cursor *cur){ ** Advance a series_cursor to its next row of output. */ static int seriesNext(sqlite3_vtab_cursor *cur){ - series_cursor *pCur = (series_cursor*)cur; - if( pCur->isDesc ){ - pCur->iValue -= pCur->iStep; - }else{ - pCur->iValue += pCur->iStep; - } - pCur->iRowid++; - return SQLITE_OK; + series_cursor *pCur = (series_cursor*)cur; + if( pCur->isDesc ){ + pCur->iValue -= pCur->iStep; + }else{ + pCur->iValue += pCur->iStep; + } + pCur->iRowid++; + return SQLITE_OK; } /* @@ -5686,20 +5686,20 @@ static int seriesNext(sqlite3_vtab_cursor *cur){ ** is currently pointing. */ static int seriesColumn( - sqlite3_vtab_cursor *cur, /* The cursor */ - sqlite3_context *ctx, /* First argument to sqlite3_result_...() */ - int i /* Which column to return */ + sqlite3_vtab_cursor *cur, /* The cursor */ + sqlite3_context *ctx, /* First argument to sqlite3_result_...() */ + int i /* Which column to return */ ){ - series_cursor *pCur = (series_cursor*)cur; - sqlite3_int64 x = 0; - switch( i ){ - case SERIES_COLUMN_START: x = pCur->mnValue; break; - case SERIES_COLUMN_STOP: x = pCur->mxValue; break; - case SERIES_COLUMN_STEP: x = pCur->iStep; break; - default: x = pCur->iValue; break; - } - sqlite3_result_int64(ctx, x); - return SQLITE_OK; + series_cursor *pCur = (series_cursor*)cur; + sqlite3_int64 x = 0; + switch( i ){ + case SERIES_COLUMN_START: x = pCur->mnValue; break; + case SERIES_COLUMN_STOP: x = pCur->mxValue; break; + case SERIES_COLUMN_STEP: x = pCur->iStep; break; + default: x = pCur->iValue; break; + } + sqlite3_result_int64(ctx, x); + return SQLITE_OK; } /* @@ -5708,9 +5708,9 @@ static int seriesColumn( ** row a value 1 more than that of the previous. */ static int seriesRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){ - series_cursor *pCur = (series_cursor*)cur; - *pRowid = pCur->iRowid; - return SQLITE_OK; + series_cursor *pCur = (series_cursor*)cur; + *pRowid = pCur->iRowid; + return SQLITE_OK; } /* @@ -5718,15 +5718,15 @@ static int seriesRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){ ** row of output. */ static int seriesEof(sqlite3_vtab_cursor *cur){ - series_cursor *pCur = (series_cursor*)cur; - if( pCur->isDesc ){ - return pCur->iValue < pCur->mnValue; - }else{ - return pCur->iValue > pCur->mxValue; - } + series_cursor *pCur = (series_cursor*)cur; + if( pCur->isDesc ){ + return pCur->iValue < pCur->mnValue; + }else{ + return pCur->iValue > pCur->mxValue; + } } -/* True to cause run-time checking of the start=, stop=, and/or step= +/* True to cause run-time checking of the start=, stop=, and/or step= ** parameters. The only reason to do this is for testing the ** constraint checking logic for virtual tables in the SQLite core. */ @@ -5737,7 +5737,7 @@ static int seriesEof(sqlite3_vtab_cursor *cur){ /* ** This method is called to "rewind" the series_cursor object back ** to the first row of output. This method is always called at least -** once prior to any call to seriesColumn() or seriesRowid() or +** once prior to any call to seriesColumn() or seriesRowid() or ** seriesEof(). ** ** The query plan selected by seriesBestIndex is passed in the idxNum @@ -5757,55 +5757,55 @@ static int seriesEof(sqlite3_vtab_cursor *cur){ ** (so that seriesEof() will return true) if the table is empty. */ static int seriesFilter( - sqlite3_vtab_cursor *pVtabCursor, - int idxNum, const char *idxStrUnused, - int argc, sqlite3_value **argv + sqlite3_vtab_cursor *pVtabCursor, + int idxNum, const char *idxStrUnused, + int argc, sqlite3_value **argv ){ - series_cursor *pCur = (series_cursor *)pVtabCursor; - int i = 0; - (void)idxStrUnused; - if( idxNum & 1 ){ - pCur->mnValue = sqlite3_value_int64(argv[i++]); - }else{ - pCur->mnValue = 0; - } - if( idxNum & 2 ){ - pCur->mxValue = sqlite3_value_int64(argv[i++]); - }else{ - pCur->mxValue = 0xffffffff; - } - if( idxNum & 4 ){ - pCur->iStep = sqlite3_value_int64(argv[i++]); - if( pCur->iStep==0 ){ - pCur->iStep = 1; - }else if( pCur->iStep<0 ){ - pCur->iStep = -pCur->iStep; - if( (idxNum & 16)==0 ) idxNum |= 8; - } - }else{ - pCur->iStep = 1; - } - for(i=0; imnValue = sqlite3_value_int64(argv[i++]); + }else{ + pCur->mnValue = 0; + } + if( idxNum & 2 ){ + pCur->mxValue = sqlite3_value_int64(argv[i++]); + }else{ + pCur->mxValue = 0xffffffff; + } + if( idxNum & 4 ){ + pCur->iStep = sqlite3_value_int64(argv[i++]); + if( pCur->iStep==0 ){ + pCur->iStep = 1; + }else if( pCur->iStep<0 ){ + pCur->iStep = -pCur->iStep; + if( (idxNum & 16)==0 ) idxNum |= 8; + } + }else{ + pCur->iStep = 1; + } + for(i=0; imnValue = 1; - pCur->mxValue = 0; - break; - } + pCur->mnValue = 1; + pCur->mxValue = 0; + break; } - if( idxNum & 8 ){ - pCur->isDesc = 1; - pCur->iValue = pCur->mxValue; - if( pCur->iStep>0 ){ - pCur->iValue -= (pCur->mxValue - pCur->mnValue)%pCur->iStep; - } - }else{ - pCur->isDesc = 0; - pCur->iValue = pCur->mnValue; + } + if( idxNum & 8 ){ + pCur->isDesc = 1; + pCur->iValue = pCur->mxValue; + if( pCur->iStep>0 ){ + pCur->iValue -= (pCur->mxValue - pCur->mnValue)%pCur->iStep; } - pCur->iRowid = 1; - return SQLITE_OK; + }else{ + pCur->isDesc = 0; + pCur->iValue = pCur->mnValue; + } + pCur->iRowid = 1; + return SQLITE_OK; } /* @@ -5825,116 +5825,116 @@ static int seriesFilter( ** (8) output in descending order */ static int seriesBestIndex( - sqlite3_vtab *pVTab, - sqlite3_index_info *pIdxInfo + sqlite3_vtab *pVTab, + sqlite3_index_info *pIdxInfo ){ - int i, j; /* Loop over constraints */ - int idxNum = 0; /* The query plan bitmask */ - int bStartSeen = 0; /* EQ constraint seen on the START column */ - int unusableMask = 0; /* Mask of unusable constraints */ - int nArg = 0; /* Number of arguments that seriesFilter() expects */ - int aIdx[3]; /* Constraints on start, stop, and step */ - const struct sqlite3_index_constraint *pConstraint; - - /* This implementation assumes that the start, stop, and step columns + int i, j; /* Loop over constraints */ + int idxNum = 0; /* The query plan bitmask */ + int bStartSeen = 0; /* EQ constraint seen on the START column */ + int unusableMask = 0; /* Mask of unusable constraints */ + int nArg = 0; /* Number of arguments that seriesFilter() expects */ + int aIdx[3]; /* Constraints on start, stop, and step */ + const struct sqlite3_index_constraint *pConstraint; + + /* This implementation assumes that the start, stop, and step columns ** are the last three columns in the virtual table. */ - assert( SERIES_COLUMN_STOP == SERIES_COLUMN_START+1 ); - assert( SERIES_COLUMN_STEP == SERIES_COLUMN_START+2 ); - - aIdx[0] = aIdx[1] = aIdx[2] = -1; - pConstraint = pIdxInfo->aConstraint; - for(i=0; inConstraint; i++, pConstraint++){ - int iCol; /* 0 for start, 1 for stop, 2 for step */ - int iMask; /* bitmask for those column */ - if( pConstraint->iColumniColumn - SERIES_COLUMN_START; - assert( iCol>=0 && iCol<=2 ); - iMask = 1 << iCol; - if( iCol==0 ) bStartSeen = 1; - if( pConstraint->usable==0 ){ - unusableMask |= iMask; - continue; - }else if( pConstraint->op==SQLITE_INDEX_CONSTRAINT_EQ ){ - idxNum |= iMask; - aIdx[iCol] = i; - } - } - for(i=0; i<3; i++){ - if( (j = aIdx[i])>=0 ){ - pIdxInfo->aConstraintUsage[j].argvIndex = ++nArg; - pIdxInfo->aConstraintUsage[j].omit = !SQLITE_SERIES_CONSTRAINT_VERIFY; - } - } - /* The current generate_column() implementation requires at least one + assert( SERIES_COLUMN_STOP == SERIES_COLUMN_START+1 ); + assert( SERIES_COLUMN_STEP == SERIES_COLUMN_START+2 ); + + aIdx[0] = aIdx[1] = aIdx[2] = -1; + pConstraint = pIdxInfo->aConstraint; + for(i=0; inConstraint; i++, pConstraint++){ + int iCol; /* 0 for start, 1 for stop, 2 for step */ + int iMask; /* bitmask for those column */ + if( pConstraint->iColumniColumn - SERIES_COLUMN_START; + assert( iCol>=0 && iCol<=2 ); + iMask = 1 << iCol; + if( iCol==0 ) bStartSeen = 1; + if( pConstraint->usable==0 ){ + unusableMask |= iMask; + continue; + }else if( pConstraint->op==SQLITE_INDEX_CONSTRAINT_EQ ){ + idxNum |= iMask; + aIdx[iCol] = i; + } + } + for(i=0; i<3; i++){ + if( (j = aIdx[i])>=0 ){ + pIdxInfo->aConstraintUsage[j].argvIndex = ++nArg; + pIdxInfo->aConstraintUsage[j].omit = !SQLITE_SERIES_CONSTRAINT_VERIFY; + } + } + /* The current generate_column() implementation requires at least one ** argument (the START value). Legacy versions assumed START=0 if the ** first argument was omitted. Compile with -DZERO_ARGUMENT_GENERATE_SERIES ** to obtain the legacy behavior */ #ifndef ZERO_ARGUMENT_GENERATE_SERIES - if( !bStartSeen ){ - sqlite3_free(pVTab->zErrMsg); - pVTab->zErrMsg = sqlite3_mprintf( - "first argument to \"generate_series()\" missing or unusable"); - return SQLITE_ERROR; - } + if( !bStartSeen ){ + sqlite3_free(pVTab->zErrMsg); + pVTab->zErrMsg = sqlite3_mprintf( + "first argument to \"generate_series()\" missing or unusable"); + return SQLITE_ERROR; + } #endif - if( (unusableMask & ~idxNum)!=0 ){ - /* The start, stop, and step columns are inputs. Therefore if there + if( (unusableMask & ~idxNum)!=0 ){ + /* The start, stop, and step columns are inputs. Therefore if there ** are unusable constraints on any of start, stop, or step then ** this plan is unusable */ - return SQLITE_CONSTRAINT; - } - if( (idxNum & 3)==3 ){ - /* Both start= and stop= boundaries are available. This is the + return SQLITE_CONSTRAINT; + } + if( (idxNum & 3)==3 ){ + /* Both start= and stop= boundaries are available. This is the ** the preferred case */ - pIdxInfo->estimatedCost = (double)(2 - ((idxNum&4)!=0)); - pIdxInfo->estimatedRows = 1000; - if( pIdxInfo->nOrderBy==1 ){ - if( pIdxInfo->aOrderBy[0].desc ){ - idxNum |= 8; - }else{ - idxNum |= 16; - } - pIdxInfo->orderByConsumed = 1; - } - }else{ - /* If either boundary is missing, we have to generate a huge span + pIdxInfo->estimatedCost = (double)(2 - ((idxNum&4)!=0)); + pIdxInfo->estimatedRows = 1000; + if( pIdxInfo->nOrderBy==1 ){ + if( pIdxInfo->aOrderBy[0].desc ){ + idxNum |= 8; + }else{ + idxNum |= 16; + } + pIdxInfo->orderByConsumed = 1; + } + }else{ + /* If either boundary is missing, we have to generate a huge span ** of numbers. Make this case very expensive so that the query ** planner will work hard to avoid it. */ - pIdxInfo->estimatedRows = 2147483647; - } - pIdxInfo->idxNum = idxNum; - return SQLITE_OK; + pIdxInfo->estimatedRows = 2147483647; + } + pIdxInfo->idxNum = idxNum; + return SQLITE_OK; } /* -** This following structure defines all the methods for the +** This following structure defines all the methods for the ** generate_series virtual table. */ static sqlite3_module seriesModule = { - 0, /* iVersion */ - 0, /* xCreate */ - seriesConnect, /* xConnect */ - seriesBestIndex, /* xBestIndex */ - seriesDisconnect, /* xDisconnect */ - 0, /* xDestroy */ - seriesOpen, /* xOpen - open a cursor */ - seriesClose, /* xClose - close a cursor */ - seriesFilter, /* xFilter - configure scan constraints */ - seriesNext, /* xNext - advance a cursor */ - seriesEof, /* xEof - check for end of scan */ - seriesColumn, /* xColumn - read data */ - seriesRowid, /* xRowid - read data */ - 0, /* xUpdate */ - 0, /* xBegin */ - 0, /* xSync */ - 0, /* xCommit */ - 0, /* xRollback */ - 0, /* xFindMethod */ - 0, /* xRename */ - 0, /* xSavepoint */ - 0, /* xRelease */ - 0, /* xRollbackTo */ - 0 /* xShadowName */ + 0, /* iVersion */ + 0, /* xCreate */ + seriesConnect, /* xConnect */ + seriesBestIndex, /* xBestIndex */ + seriesDisconnect, /* xDisconnect */ + 0, /* xDestroy */ + seriesOpen, /* xOpen - open a cursor */ + seriesClose, /* xClose - close a cursor */ + seriesFilter, /* xFilter - configure scan constraints */ + seriesNext, /* xNext - advance a cursor */ + seriesEof, /* xEof - check for end of scan */ + seriesColumn, /* xColumn - read data */ + seriesRowid, /* xRowid - read data */ + 0, /* xUpdate */ + 0, /* xBegin */ + 0, /* xSync */ + 0, /* xCommit */ + 0, /* xRollback */ + 0, /* xFindMethod */ + 0, /* xRename */ + 0, /* xSavepoint */ + 0, /* xRelease */ + 0, /* xRollbackTo */ + 0 /* xShadowName */ }; #endif /* SQLITE_OMIT_VIRTUALTABLE */ @@ -5943,21 +5943,21 @@ static sqlite3_module seriesModule = { #endif int sqlite3_series_init( - sqlite3 *db, - char **pzErrMsg, - const sqlite3_api_routines *pApi + sqlite3 *db, + char **pzErrMsg, + const sqlite3_api_routines *pApi ){ - int rc = SQLITE_OK; - SQLITE_EXTENSION_INIT2(pApi); + int rc = SQLITE_OK; + SQLITE_EXTENSION_INIT2(pApi); #ifndef SQLITE_OMIT_VIRTUALTABLE - if( sqlite3_libversion_number()<3008012 && pzErrMsg!=0 ){ - *pzErrMsg = sqlite3_mprintf( - "generate_series() requires SQLite 3.8.12 or later"); - return SQLITE_ERROR; - } - rc = sqlite3_create_module(db, "generate_series", &seriesModule, 0); + if( sqlite3_libversion_number()<3008012 && pzErrMsg!=0 ){ + *pzErrMsg = sqlite3_mprintf( + "generate_series() requires SQLite 3.8.12 or later"); + return SQLITE_ERROR; + } + rc = sqlite3_create_module(db, "generate_series", &seriesModule, 0); #endif - return rc; + return rc; } /************************* End ../ext/misc/series.c ********************/ @@ -6067,17 +6067,17 @@ typedef unsigned short ReStateNumber; ** number of actives states is small. */ typedef struct ReStateSet { - unsigned nState; /* Number of current states */ - ReStateNumber *aState; /* Current states */ + unsigned nState; /* Number of current states */ + ReStateNumber *aState; /* Current states */ } ReStateSet; /* An input string read one character at a time. */ typedef struct ReInput ReInput; struct ReInput { - const unsigned char *z; /* All text */ - int i; /* Next byte to read */ - int mx; /* EOF when i>=mx */ + const unsigned char *z; /* All text */ + int i; /* Next byte to read */ + int mx; /* EOF when i>=mx */ }; /* A compiled NFA (or an NFA that is in the process of being compiled) is @@ -6085,265 +6085,265 @@ struct ReInput { */ typedef struct ReCompiled ReCompiled; struct ReCompiled { - ReInput sIn; /* Regular expression text */ - const char *zErr; /* Error message to return */ - char *aOp; /* Operators for the virtual machine */ - int *aArg; /* Arguments to each operator */ - unsigned (*xNextChar)(ReInput*); /* Next character function */ - unsigned char zInit[12]; /* Initial text to match */ - int nInit; /* Number of characters in zInit */ - unsigned nState; /* Number of entries in aOp[] and aArg[] */ - unsigned nAlloc; /* Slots allocated for aOp[] and aArg[] */ + ReInput sIn; /* Regular expression text */ + const char *zErr; /* Error message to return */ + char *aOp; /* Operators for the virtual machine */ + int *aArg; /* Arguments to each operator */ + unsigned (*xNextChar)(ReInput*); /* Next character function */ + unsigned char zInit[12]; /* Initial text to match */ + int nInit; /* Number of characters in zInit */ + unsigned nState; /* Number of entries in aOp[] and aArg[] */ + unsigned nAlloc; /* Slots allocated for aOp[] and aArg[] */ }; /* Add a state to the given state set if it is not already there */ static void re_add_state(ReStateSet *pSet, int newState){ - unsigned i; - for(i=0; inState; i++) if( pSet->aState[i]==newState ) return; - pSet->aState[pSet->nState++] = (ReStateNumber)newState; + unsigned i; + for(i=0; inState; i++) if( pSet->aState[i]==newState ) return; + pSet->aState[pSet->nState++] = (ReStateNumber)newState; } /* Extract the next unicode character from *pzIn and return it. Advance ** *pzIn to the first byte past the end of the character returned. To -** be clear: this routine converts utf8 to unicode. This routine is +** be clear: this routine converts utf8 to unicode. This routine is ** optimized for the common case where the next character is a single byte. */ static unsigned re_next_char(ReInput *p){ - unsigned c; - if( p->i>=p->mx ) return 0; - c = p->z[p->i++]; - if( c>=0x80 ){ - if( (c&0xe0)==0xc0 && p->imx && (p->z[p->i]&0xc0)==0x80 ){ - c = (c&0x1f)<<6 | (p->z[p->i++]&0x3f); - if( c<0x80 ) c = 0xfffd; - }else if( (c&0xf0)==0xe0 && p->i+1mx && (p->z[p->i]&0xc0)==0x80 - && (p->z[p->i+1]&0xc0)==0x80 ){ - c = (c&0x0f)<<12 | ((p->z[p->i]&0x3f)<<6) | (p->z[p->i+1]&0x3f); - p->i += 2; - if( c<=0x7ff || (c>=0xd800 && c<=0xdfff) ) c = 0xfffd; - }else if( (c&0xf8)==0xf0 && p->i+3mx && (p->z[p->i]&0xc0)==0x80 - && (p->z[p->i+1]&0xc0)==0x80 && (p->z[p->i+2]&0xc0)==0x80 ){ - c = (c&0x07)<<18 | ((p->z[p->i]&0x3f)<<12) | ((p->z[p->i+1]&0x3f)<<6) - | (p->z[p->i+2]&0x3f); - p->i += 3; - if( c<=0xffff || c>0x10ffff ) c = 0xfffd; - }else{ - c = 0xfffd; - } + unsigned c; + if( p->i>=p->mx ) return 0; + c = p->z[p->i++]; + if( c>=0x80 ){ + if( (c&0xe0)==0xc0 && p->imx && (p->z[p->i]&0xc0)==0x80 ){ + c = (c&0x1f)<<6 | (p->z[p->i++]&0x3f); + if( c<0x80 ) c = 0xfffd; + }else if( (c&0xf0)==0xe0 && p->i+1mx && (p->z[p->i]&0xc0)==0x80 + && (p->z[p->i+1]&0xc0)==0x80 ){ + c = (c&0x0f)<<12 | ((p->z[p->i]&0x3f)<<6) | (p->z[p->i+1]&0x3f); + p->i += 2; + if( c<=0x7ff || (c>=0xd800 && c<=0xdfff) ) c = 0xfffd; + }else if( (c&0xf8)==0xf0 && p->i+3mx && (p->z[p->i]&0xc0)==0x80 + && (p->z[p->i+1]&0xc0)==0x80 && (p->z[p->i+2]&0xc0)==0x80 ){ + c = (c&0x07)<<18 | ((p->z[p->i]&0x3f)<<12) | ((p->z[p->i+1]&0x3f)<<6) + | (p->z[p->i+2]&0x3f); + p->i += 3; + if( c<=0xffff || c>0x10ffff ) c = 0xfffd; + }else{ + c = 0xfffd; } - return c; + } + return c; } static unsigned re_next_char_nocase(ReInput *p){ - unsigned c = re_next_char(p); - if( c>='A' && c<='Z' ) c += 'a' - 'A'; - return c; + unsigned c = re_next_char(p); + if( c>='A' && c<='Z' ) c += 'a' - 'A'; + return c; } /* Return true if c is a perl "word" character: [A-Za-z0-9_] */ static int re_word_char(int c){ - return (c>='0' && c<='9') || (c>='a' && c<='z') - || (c>='A' && c<='Z') || c=='_'; + return (c>='0' && c<='9') || (c>='a' && c<='z') + || (c>='A' && c<='Z') || c=='_'; } /* Return true if c is a "digit" character: [0-9] */ static int re_digit_char(int c){ - return (c>='0' && c<='9'); + return (c>='0' && c<='9'); } /* Return true if c is a perl "space" character: [ \t\r\n\v\f] */ static int re_space_char(int c){ - return c==' ' || c=='\t' || c=='\n' || c=='\r' || c=='\v' || c=='\f'; + return c==' ' || c=='\t' || c=='\n' || c=='\r' || c=='\v' || c=='\f'; } /* Run a compiled regular expression on the zero-terminated input ** string zIn[]. Return true on a match and false if there is no match. */ static int re_match(ReCompiled *pRe, const unsigned char *zIn, int nIn){ - ReStateSet aStateSet[2], *pThis, *pNext; - ReStateNumber aSpace[100]; - ReStateNumber *pToFree; - unsigned int i = 0; - unsigned int iSwap = 0; - int c = RE_EOF+1; - int cPrev = 0; - int rc = 0; - ReInput in; - - in.z = zIn; - in.i = 0; - in.mx = nIn>=0 ? nIn : (int)strlen((char const*)zIn); - - /* Look for the initial prefix match, if there is one. */ - if( pRe->nInit ){ - unsigned char x = pRe->zInit[0]; - while( in.i+pRe->nInit<=in.mx - && (zIn[in.i]!=x || - strncmp((const char*)zIn+in.i, (const char*)pRe->zInit, pRe->nInit)!=0) - ){ - in.i++; + ReStateSet aStateSet[2], *pThis, *pNext; + ReStateNumber aSpace[100]; + ReStateNumber *pToFree; + unsigned int i = 0; + unsigned int iSwap = 0; + int c = RE_EOF+1; + int cPrev = 0; + int rc = 0; + ReInput in; + + in.z = zIn; + in.i = 0; + in.mx = nIn>=0 ? nIn : (int)strlen((char const*)zIn); + + /* Look for the initial prefix match, if there is one. */ + if( pRe->nInit ){ + unsigned char x = pRe->zInit[0]; + while( in.i+pRe->nInit<=in.mx + && (zIn[in.i]!=x || + strncmp((const char*)zIn+in.i, (const char*)pRe->zInit, pRe->nInit)!=0) + ){ + in.i++; + } + if( in.i+pRe->nInit>in.mx ) return 0; + } + + if( pRe->nState<=(sizeof(aSpace)/(sizeof(aSpace[0])*2)) ){ + pToFree = 0; + aStateSet[0].aState = aSpace; + }else{ + pToFree = sqlite3_malloc64( sizeof(ReStateNumber)*2*pRe->nState ); + if( pToFree==0 ) return -1; + aStateSet[0].aState = pToFree; + } + aStateSet[1].aState = &aStateSet[0].aState[pRe->nState]; + pNext = &aStateSet[1]; + pNext->nState = 0; + re_add_state(pNext, 0); + while( c!=RE_EOF && pNext->nState>0 ){ + cPrev = c; + c = pRe->xNextChar(&in); + pThis = pNext; + pNext = &aStateSet[iSwap]; + iSwap = 1 - iSwap; + pNext->nState = 0; + for(i=0; inState; i++){ + int x = pThis->aState[i]; + switch( pRe->aOp[x] ){ + case RE_OP_MATCH: { + if( pRe->aArg[x]==c ) re_add_state(pNext, x+1); + break; + } + case RE_OP_ANY: { + if( c!=0 ) re_add_state(pNext, x+1); + break; + } + case RE_OP_WORD: { + if( re_word_char(c) ) re_add_state(pNext, x+1); + break; + } + case RE_OP_NOTWORD: { + if( !re_word_char(c) && c!=0 ) re_add_state(pNext, x+1); + break; + } + case RE_OP_DIGIT: { + if( re_digit_char(c) ) re_add_state(pNext, x+1); + break; + } + case RE_OP_NOTDIGIT: { + if( !re_digit_char(c) && c!=0 ) re_add_state(pNext, x+1); + break; + } + case RE_OP_SPACE: { + if( re_space_char(c) ) re_add_state(pNext, x+1); + break; + } + case RE_OP_NOTSPACE: { + if( !re_space_char(c) && c!=0 ) re_add_state(pNext, x+1); + break; + } + case RE_OP_BOUNDARY: { + if( re_word_char(c)!=re_word_char(cPrev) ) re_add_state(pThis, x+1); + break; + } + case RE_OP_ANYSTAR: { + re_add_state(pNext, x); + re_add_state(pThis, x+1); + break; + } + case RE_OP_FORK: { + re_add_state(pThis, x+pRe->aArg[x]); + re_add_state(pThis, x+1); + break; + } + case RE_OP_GOTO: { + re_add_state(pThis, x+pRe->aArg[x]); + break; + } + case RE_OP_ACCEPT: { + rc = 1; + goto re_match_end; + } + case RE_OP_CC_EXC: { + if( c==0 ) break; + /* fall-through */ goto re_op_cc_inc; + } + case RE_OP_CC_INC: re_op_cc_inc: { + int j = 1; + int n = pRe->aArg[x]; + int hit = 0; + for(j=1; j>0 && jaOp[x+j]==RE_OP_CC_VALUE ){ + if( pRe->aArg[x+j]==c ){ + hit = 1; + j = -1; + } + }else{ + if( pRe->aArg[x+j]<=c && pRe->aArg[x+j+1]>=c ){ + hit = 1; + j = -1; + }else{ + j++; + } + } + } + if( pRe->aOp[x]==RE_OP_CC_EXC ) hit = !hit; + if( hit ) re_add_state(pNext, x+n); + break; } - if( in.i+pRe->nInit>in.mx ) return 0; + } } - - if( pRe->nState<=(sizeof(aSpace)/(sizeof(aSpace[0])*2)) ){ - pToFree = 0; - aStateSet[0].aState = aSpace; - }else{ - pToFree = sqlite3_malloc64( sizeof(ReStateNumber)*2*pRe->nState ); - if( pToFree==0 ) return -1; - aStateSet[0].aState = pToFree; - } - aStateSet[1].aState = &aStateSet[0].aState[pRe->nState]; - pNext = &aStateSet[1]; - pNext->nState = 0; - re_add_state(pNext, 0); - while( c!=RE_EOF && pNext->nState>0 ){ - cPrev = c; - c = pRe->xNextChar(&in); - pThis = pNext; - pNext = &aStateSet[iSwap]; - iSwap = 1 - iSwap; - pNext->nState = 0; - for(i=0; inState; i++){ - int x = pThis->aState[i]; - switch( pRe->aOp[x] ){ - case RE_OP_MATCH: { - if( pRe->aArg[x]==c ) re_add_state(pNext, x+1); - break; - } - case RE_OP_ANY: { - if( c!=0 ) re_add_state(pNext, x+1); - break; - } - case RE_OP_WORD: { - if( re_word_char(c) ) re_add_state(pNext, x+1); - break; - } - case RE_OP_NOTWORD: { - if( !re_word_char(c) && c!=0 ) re_add_state(pNext, x+1); - break; - } - case RE_OP_DIGIT: { - if( re_digit_char(c) ) re_add_state(pNext, x+1); - break; - } - case RE_OP_NOTDIGIT: { - if( !re_digit_char(c) && c!=0 ) re_add_state(pNext, x+1); - break; - } - case RE_OP_SPACE: { - if( re_space_char(c) ) re_add_state(pNext, x+1); - break; - } - case RE_OP_NOTSPACE: { - if( !re_space_char(c) && c!=0 ) re_add_state(pNext, x+1); - break; - } - case RE_OP_BOUNDARY: { - if( re_word_char(c)!=re_word_char(cPrev) ) re_add_state(pThis, x+1); - break; - } - case RE_OP_ANYSTAR: { - re_add_state(pNext, x); - re_add_state(pThis, x+1); - break; - } - case RE_OP_FORK: { - re_add_state(pThis, x+pRe->aArg[x]); - re_add_state(pThis, x+1); - break; - } - case RE_OP_GOTO: { - re_add_state(pThis, x+pRe->aArg[x]); - break; - } - case RE_OP_ACCEPT: { - rc = 1; - goto re_match_end; - } - case RE_OP_CC_EXC: { - if( c==0 ) break; - /* fall-through */ goto re_op_cc_inc; - } - case RE_OP_CC_INC: re_op_cc_inc: { - int j = 1; - int n = pRe->aArg[x]; - int hit = 0; - for(j=1; j>0 && jaOp[x+j]==RE_OP_CC_VALUE ){ - if( pRe->aArg[x+j]==c ){ - hit = 1; - j = -1; - } - }else{ - if( pRe->aArg[x+j]<=c && pRe->aArg[x+j+1]>=c ){ - hit = 1; - j = -1; - }else{ - j++; - } - } - } - if( pRe->aOp[x]==RE_OP_CC_EXC ) hit = !hit; - if( hit ) re_add_state(pNext, x+n); - break; - } - } - } - } - for(i=0; inState; i++){ - if( pRe->aOp[pNext->aState[i]]==RE_OP_ACCEPT ){ rc = 1; break; } - } -re_match_end: - sqlite3_free(pToFree); - return rc; -} + } + for(i=0; inState; i++){ + if( pRe->aOp[pNext->aState[i]]==RE_OP_ACCEPT ){ rc = 1; break; } + } +re_match_end: + sqlite3_free(pToFree); + return rc; +} /* Resize the opcode and argument arrays for an RE under construction. */ static int re_resize(ReCompiled *p, int N){ - char *aOp; - int *aArg; - aOp = sqlite3_realloc64(p->aOp, N*sizeof(p->aOp[0])); - if( aOp==0 ) return 1; - p->aOp = aOp; - aArg = sqlite3_realloc64(p->aArg, N*sizeof(p->aArg[0])); - if( aArg==0 ) return 1; - p->aArg = aArg; - p->nAlloc = N; - return 0; + char *aOp; + int *aArg; + aOp = sqlite3_realloc64(p->aOp, N*sizeof(p->aOp[0])); + if( aOp==0 ) return 1; + p->aOp = aOp; + aArg = sqlite3_realloc64(p->aArg, N*sizeof(p->aArg[0])); + if( aArg==0 ) return 1; + p->aArg = aArg; + p->nAlloc = N; + return 0; } /* Insert a new opcode and argument into an RE under construction. The ** insertion point is just prior to existing opcode iBefore. */ static int re_insert(ReCompiled *p, int iBefore, int op, int arg){ - int i; - if( p->nAlloc<=p->nState && re_resize(p, p->nAlloc*2) ) return 0; - for(i=p->nState; i>iBefore; i--){ - p->aOp[i] = p->aOp[i-1]; - p->aArg[i] = p->aArg[i-1]; - } - p->nState++; - p->aOp[iBefore] = (char)op; - p->aArg[iBefore] = arg; - return iBefore; + int i; + if( p->nAlloc<=p->nState && re_resize(p, p->nAlloc*2) ) return 0; + for(i=p->nState; i>iBefore; i--){ + p->aOp[i] = p->aOp[i-1]; + p->aArg[i] = p->aArg[i-1]; + } + p->nState++; + p->aOp[iBefore] = (char)op; + p->aArg[iBefore] = arg; + return iBefore; } /* Append a new opcode and argument to the end of the RE under construction. */ static int re_append(ReCompiled *p, int op, int arg){ - return re_insert(p, p->nState, op, arg); + return re_insert(p, p->nState, op, arg); } /* Make a copy of N opcodes starting at iStart onto the end of the RE ** under construction. */ static void re_copy(ReCompiled *p, int iStart, int N){ - if( p->nState+N>=p->nAlloc && re_resize(p, p->nAlloc*2+N) ) return; - memcpy(&p->aOp[p->nState], &p->aOp[iStart], N*sizeof(p->aOp[0])); - memcpy(&p->aArg[p->nState], &p->aArg[iStart], N*sizeof(p->aArg[0])); - p->nState += N; + if( p->nState+N>=p->nAlloc && re_resize(p, p->nAlloc*2+N) ) return; + memcpy(&p->aOp[p->nState], &p->aOp[iStart], N*sizeof(p->aOp[0])); + memcpy(&p->aArg[p->nState], &p->aArg[iStart], N*sizeof(p->aArg[0])); + p->nState += N; } /* Return true if c is a hexadecimal digit character: [0-9a-fA-F] @@ -6351,57 +6351,57 @@ static void re_copy(ReCompiled *p, int iStart, int N){ ** c is not a hex digit *pV is unchanged. */ static int re_hex(int c, int *pV){ - if( c>='0' && c<='9' ){ - c -= '0'; - }else if( c>='a' && c<='f' ){ - c -= 'a' - 10; - }else if( c>='A' && c<='F' ){ - c -= 'A' - 10; - }else{ - return 0; - } - *pV = (*pV)*16 + (c & 0xff); - return 1; + if( c>='0' && c<='9' ){ + c -= '0'; + }else if( c>='a' && c<='f' ){ + c -= 'a' - 10; + }else if( c>='A' && c<='F' ){ + c -= 'A' - 10; + }else{ + return 0; + } + *pV = (*pV)*16 + (c & 0xff); + return 1; } /* A backslash character has been seen, read the next character and ** return its interpretation. */ static unsigned re_esc_char(ReCompiled *p){ - static const char zEsc[] = "afnrtv\\()*.+?[$^{|}]"; - static const char zTrans[] = "\a\f\n\r\t\v"; - int i, v = 0; - char c; - if( p->sIn.i>=p->sIn.mx ) return 0; - c = p->sIn.z[p->sIn.i]; - if( c=='u' && p->sIn.i+4sIn.mx ){ - const unsigned char *zIn = p->sIn.z + p->sIn.i; - if( re_hex(zIn[1],&v) - && re_hex(zIn[2],&v) - && re_hex(zIn[3],&v) - && re_hex(zIn[4],&v) - ){ - p->sIn.i += 5; - return v; - } - } - if( c=='x' && p->sIn.i+2sIn.mx ){ - const unsigned char *zIn = p->sIn.z + p->sIn.i; - if( re_hex(zIn[1],&v) - && re_hex(zIn[2],&v) - ){ - p->sIn.i += 3; - return v; - } - } - for(i=0; zEsc[i] && zEsc[i]!=c; i++){} - if( zEsc[i] ){ - if( i<6 ) c = zTrans[i]; - p->sIn.i++; - }else{ - p->zErr = "unknown \\ escape"; + static const char zEsc[] = "afnrtv\\()*.+?[$^{|}]"; + static const char zTrans[] = "\a\f\n\r\t\v"; + int i, v = 0; + char c; + if( p->sIn.i>=p->sIn.mx ) return 0; + c = p->sIn.z[p->sIn.i]; + if( c=='u' && p->sIn.i+4sIn.mx ){ + const unsigned char *zIn = p->sIn.z + p->sIn.i; + if( re_hex(zIn[1],&v) + && re_hex(zIn[2],&v) + && re_hex(zIn[3],&v) + && re_hex(zIn[4],&v) + ){ + p->sIn.i += 5; + return v; + } + } + if( c=='x' && p->sIn.i+2sIn.mx ){ + const unsigned char *zIn = p->sIn.z + p->sIn.i; + if( re_hex(zIn[1],&v) + && re_hex(zIn[2],&v) + ){ + p->sIn.i += 3; + return v; } - return c; + } + for(i=0; zEsc[i] && zEsc[i]!=c; i++){} + if( zEsc[i] ){ + if( i<6 ) c = zTrans[i]; + p->sIn.i++; + }else{ + p->zErr = "unknown \\ escape"; + } + return c; } /* Forward declaration */ @@ -6409,7 +6409,7 @@ static const char *re_subcompile_string(ReCompiled*); /* Peek at the next byte of input */ static unsigned char rePeek(ReCompiled *p){ - return p->sIn.isIn.mx ? p->sIn.z[p->sIn.i] : 0; + return p->sIn.isIn.mx ? p->sIn.z[p->sIn.i] : 0; } /* Compile RE text into a sequence of opcodes. Continue up to the @@ -6417,21 +6417,21 @@ static unsigned char rePeek(ReCompiled *p){ ** return a pointer to the error message string. */ static const char *re_subcompile_re(ReCompiled *p){ - const char *zErr; - int iStart, iEnd, iGoto; - iStart = p->nState; + const char *zErr; + int iStart, iEnd, iGoto; + iStart = p->nState; + zErr = re_subcompile_string(p); + if( zErr ) return zErr; + while( rePeek(p)=='|' ){ + iEnd = p->nState; + re_insert(p, iStart, RE_OP_FORK, iEnd + 2 - iStart); + iGoto = re_append(p, RE_OP_GOTO, 0); + p->sIn.i++; zErr = re_subcompile_string(p); if( zErr ) return zErr; - while( rePeek(p)=='|' ){ - iEnd = p->nState; - re_insert(p, iStart, RE_OP_FORK, iEnd + 2 - iStart); - iGoto = re_append(p, RE_OP_GOTO, 0); - p->sIn.i++; - zErr = re_subcompile_string(p); - if( zErr ) return zErr; - p->aArg[iGoto] = p->nState - iGoto; - } - return 0; + p->aArg[iGoto] = p->nState - iGoto; + } + return 0; } /* Compile an element of regular expression text (anything that can be @@ -6439,138 +6439,138 @@ static const char *re_subcompile_re(ReCompiled *p){ ** to the error message if there is a problem. */ static const char *re_subcompile_string(ReCompiled *p){ - int iPrev = -1; - int iStart; - unsigned c; - const char *zErr; - while( (c = p->xNextChar(&p->sIn))!=0 ){ - iStart = p->nState; - switch( c ){ - case '|': - case '$': - case ')': { - p->sIn.i--; - return 0; - } - case '(': { - zErr = re_subcompile_re(p); - if( zErr ) return zErr; - if( rePeek(p)!=')' ) return "unmatched '('"; - p->sIn.i++; - break; - } - case '.': { - if( rePeek(p)=='*' ){ - re_append(p, RE_OP_ANYSTAR, 0); - p->sIn.i++; - }else{ - re_append(p, RE_OP_ANY, 0); - } - break; - } - case '*': { - if( iPrev<0 ) return "'*' without operand"; - re_insert(p, iPrev, RE_OP_GOTO, p->nState - iPrev + 1); - re_append(p, RE_OP_FORK, iPrev - p->nState + 1); - break; - } - case '+': { - if( iPrev<0 ) return "'+' without operand"; - re_append(p, RE_OP_FORK, iPrev - p->nState); - break; - } - case '?': { - if( iPrev<0 ) return "'?' without operand"; - re_insert(p, iPrev, RE_OP_FORK, p->nState - iPrev+1); - break; - } - case '{': { - int m = 0, n = 0; - int sz, j; - if( iPrev<0 ) return "'{m,n}' without operand"; - while( (c=rePeek(p))>='0' && c<='9' ){ m = m*10 + c - '0'; p->sIn.i++; } - n = m; - if( c==',' ){ - p->sIn.i++; - n = 0; - while( (c=rePeek(p))>='0' && c<='9' ){ n = n*10 + c-'0'; p->sIn.i++; } - } - if( c!='}' ) return "unmatched '{'"; - if( n>0 && nsIn.i++; - sz = p->nState - iPrev; - if( m==0 ){ - if( n==0 ) return "both m and n are zero in '{m,n}'"; - re_insert(p, iPrev, RE_OP_FORK, sz+1); - n--; - }else{ - for(j=1; j0 ){ - re_append(p, RE_OP_FORK, -sz); - } - break; - } - case '[': { - int iFirst = p->nState; - if( rePeek(p)=='^' ){ - re_append(p, RE_OP_CC_EXC, 0); - p->sIn.i++; - }else{ - re_append(p, RE_OP_CC_INC, 0); - } - while( (c = p->xNextChar(&p->sIn))!=0 ){ - if( c=='[' && rePeek(p)==':' ){ - return "POSIX character classes not supported"; - } - if( c=='\\' ) c = re_esc_char(p); - if( rePeek(p)=='-' ){ - re_append(p, RE_OP_CC_RANGE, c); - p->sIn.i++; - c = p->xNextChar(&p->sIn); - if( c=='\\' ) c = re_esc_char(p); - re_append(p, RE_OP_CC_RANGE, c); - }else{ - re_append(p, RE_OP_CC_VALUE, c); - } - if( rePeek(p)==']' ){ p->sIn.i++; break; } - } - if( c==0 ) return "unclosed '['"; - p->aArg[iFirst] = p->nState - iFirst; - break; - } - case '\\': { - int specialOp = 0; - switch( rePeek(p) ){ - case 'b': specialOp = RE_OP_BOUNDARY; break; - case 'd': specialOp = RE_OP_DIGIT; break; - case 'D': specialOp = RE_OP_NOTDIGIT; break; - case 's': specialOp = RE_OP_SPACE; break; - case 'S': specialOp = RE_OP_NOTSPACE; break; - case 'w': specialOp = RE_OP_WORD; break; - case 'W': specialOp = RE_OP_NOTWORD; break; - } - if( specialOp ){ - p->sIn.i++; - re_append(p, specialOp, 0); - }else{ - c = re_esc_char(p); - re_append(p, RE_OP_MATCH, c); - } - break; - } - default: { - re_append(p, RE_OP_MATCH, c); - break; - } + int iPrev = -1; + int iStart; + unsigned c; + const char *zErr; + while( (c = p->xNextChar(&p->sIn))!=0 ){ + iStart = p->nState; + switch( c ){ + case '|': + case '$': + case ')': { + p->sIn.i--; + return 0; + } + case '(': { + zErr = re_subcompile_re(p); + if( zErr ) return zErr; + if( rePeek(p)!=')' ) return "unmatched '('"; + p->sIn.i++; + break; + } + case '.': { + if( rePeek(p)=='*' ){ + re_append(p, RE_OP_ANYSTAR, 0); + p->sIn.i++; + }else{ + re_append(p, RE_OP_ANY, 0); + } + break; + } + case '*': { + if( iPrev<0 ) return "'*' without operand"; + re_insert(p, iPrev, RE_OP_GOTO, p->nState - iPrev + 1); + re_append(p, RE_OP_FORK, iPrev - p->nState + 1); + break; + } + case '+': { + if( iPrev<0 ) return "'+' without operand"; + re_append(p, RE_OP_FORK, iPrev - p->nState); + break; + } + case '?': { + if( iPrev<0 ) return "'?' without operand"; + re_insert(p, iPrev, RE_OP_FORK, p->nState - iPrev+1); + break; + } + case '{': { + int m = 0, n = 0; + int sz, j; + if( iPrev<0 ) return "'{m,n}' without operand"; + while( (c=rePeek(p))>='0' && c<='9' ){ m = m*10 + c - '0'; p->sIn.i++; } + n = m; + if( c==',' ){ + p->sIn.i++; + n = 0; + while( (c=rePeek(p))>='0' && c<='9' ){ n = n*10 + c-'0'; p->sIn.i++; } + } + if( c!='}' ) return "unmatched '{'"; + if( n>0 && nsIn.i++; + sz = p->nState - iPrev; + if( m==0 ){ + if( n==0 ) return "both m and n are zero in '{m,n}'"; + re_insert(p, iPrev, RE_OP_FORK, sz+1); + n--; + }else{ + for(j=1; j0 ){ + re_append(p, RE_OP_FORK, -sz); + } + break; + } + case '[': { + int iFirst = p->nState; + if( rePeek(p)=='^' ){ + re_append(p, RE_OP_CC_EXC, 0); + p->sIn.i++; + }else{ + re_append(p, RE_OP_CC_INC, 0); + } + while( (c = p->xNextChar(&p->sIn))!=0 ){ + if( c=='[' && rePeek(p)==':' ){ + return "POSIX character classes not supported"; + } + if( c=='\\' ) c = re_esc_char(p); + if( rePeek(p)=='-' ){ + re_append(p, RE_OP_CC_RANGE, c); + p->sIn.i++; + c = p->xNextChar(&p->sIn); + if( c=='\\' ) c = re_esc_char(p); + re_append(p, RE_OP_CC_RANGE, c); + }else{ + re_append(p, RE_OP_CC_VALUE, c); + } + if( rePeek(p)==']' ){ p->sIn.i++; break; } + } + if( c==0 ) return "unclosed '['"; + p->aArg[iFirst] = p->nState - iFirst; + break; + } + case '\\': { + int specialOp = 0; + switch( rePeek(p) ){ + case 'b': specialOp = RE_OP_BOUNDARY; break; + case 'd': specialOp = RE_OP_DIGIT; break; + case 'D': specialOp = RE_OP_NOTDIGIT; break; + case 's': specialOp = RE_OP_SPACE; break; + case 'S': specialOp = RE_OP_NOTSPACE; break; + case 'w': specialOp = RE_OP_WORD; break; + case 'W': specialOp = RE_OP_NOTWORD; break; + } + if( specialOp ){ + p->sIn.i++; + re_append(p, specialOp, 0); + }else{ + c = re_esc_char(p); + re_append(p, RE_OP_MATCH, c); } - iPrev = iStart; + break; + } + default: { + re_append(p, RE_OP_MATCH, c); + break; + } } - return 0; + iPrev = iStart; + } + return 0; } /* Free and reclaim all the memory used by a previously compiled @@ -6578,11 +6578,11 @@ static const char *re_subcompile_string(ReCompiled *p){ ** for every call to re_compile() to avoid memory leaks. */ static void re_free(ReCompiled *pRe){ - if( pRe ){ - sqlite3_free(pRe->aOp); - sqlite3_free(pRe->aArg); - sqlite3_free(pRe); - } + if( pRe ){ + sqlite3_free(pRe->aOp); + sqlite3_free(pRe->aArg); + sqlite3_free(pRe); + } } /* @@ -6592,74 +6592,74 @@ static void re_free(ReCompiled *pRe){ ** error message if something goes wrong. */ static const char *re_compile(ReCompiled **ppRe, const char *zIn, int noCase){ - ReCompiled *pRe; - const char *zErr; - int i, j; - - *ppRe = 0; - pRe = sqlite3_malloc( sizeof(*pRe) ); - if( pRe==0 ){ - return "out of memory"; - } - memset(pRe, 0, sizeof(*pRe)); - pRe->xNextChar = noCase ? re_next_char_nocase : re_next_char; - if( re_resize(pRe, 30) ){ - re_free(pRe); - return "out of memory"; - } - if( zIn[0]=='^' ){ - zIn++; - }else{ - re_append(pRe, RE_OP_ANYSTAR, 0); - } - pRe->sIn.z = (unsigned char*)zIn; - pRe->sIn.i = 0; - pRe->sIn.mx = (int)strlen(zIn); - zErr = re_subcompile_re(pRe); - if( zErr ){ - re_free(pRe); - return zErr; - } - if( rePeek(pRe)=='$' && pRe->sIn.i+1>=pRe->sIn.mx ){ - re_append(pRe, RE_OP_MATCH, RE_EOF); - re_append(pRe, RE_OP_ACCEPT, 0); - *ppRe = pRe; - }else if( pRe->sIn.i>=pRe->sIn.mx ){ - re_append(pRe, RE_OP_ACCEPT, 0); - *ppRe = pRe; - }else{ - re_free(pRe); - return "unrecognized character"; - } - - /* The following is a performance optimization. If the regex begins with + ReCompiled *pRe; + const char *zErr; + int i, j; + + *ppRe = 0; + pRe = sqlite3_malloc( sizeof(*pRe) ); + if( pRe==0 ){ + return "out of memory"; + } + memset(pRe, 0, sizeof(*pRe)); + pRe->xNextChar = noCase ? re_next_char_nocase : re_next_char; + if( re_resize(pRe, 30) ){ + re_free(pRe); + return "out of memory"; + } + if( zIn[0]=='^' ){ + zIn++; + }else{ + re_append(pRe, RE_OP_ANYSTAR, 0); + } + pRe->sIn.z = (unsigned char*)zIn; + pRe->sIn.i = 0; + pRe->sIn.mx = (int)strlen(zIn); + zErr = re_subcompile_re(pRe); + if( zErr ){ + re_free(pRe); + return zErr; + } + if( rePeek(pRe)=='$' && pRe->sIn.i+1>=pRe->sIn.mx ){ + re_append(pRe, RE_OP_MATCH, RE_EOF); + re_append(pRe, RE_OP_ACCEPT, 0); + *ppRe = pRe; + }else if( pRe->sIn.i>=pRe->sIn.mx ){ + re_append(pRe, RE_OP_ACCEPT, 0); + *ppRe = pRe; + }else{ + re_free(pRe); + return "unrecognized character"; + } + + /* The following is a performance optimization. If the regex begins with ** ".*" (if the input regex lacks an initial "^") and afterwards there are ** one or more matching characters, enter those matching characters into - ** zInit[]. The re_match() routine can then search ahead in the input + ** zInit[]. The re_match() routine can then search ahead in the input ** string looking for the initial match without having to run the whole ** regex engine over the string. Do not worry able trying to match ** unicode characters beyond plane 0 - those are very rare and this is ** just an optimization. */ - if( pRe->aOp[0]==RE_OP_ANYSTAR && !noCase ){ - for(j=0, i=1; j<(int)sizeof(pRe->zInit)-2 && pRe->aOp[i]==RE_OP_MATCH; i++){ - unsigned x = pRe->aArg[i]; - if( x<=127 ){ - pRe->zInit[j++] = (unsigned char)x; - }else if( x<=0xfff ){ - pRe->zInit[j++] = (unsigned char)(0xc0 | (x>>6)); - pRe->zInit[j++] = 0x80 | (x&0x3f); - }else if( x<=0xffff ){ - pRe->zInit[j++] = (unsigned char)(0xd0 | (x>>12)); - pRe->zInit[j++] = 0x80 | ((x>>6)&0x3f); - pRe->zInit[j++] = 0x80 | (x&0x3f); - }else{ - break; - } - } - if( j>0 && pRe->zInit[j-1]==0 ) j--; - pRe->nInit = j; - } - return pRe->zErr; + if( pRe->aOp[0]==RE_OP_ANYSTAR && !noCase ){ + for(j=0, i=1; j<(int)sizeof(pRe->zInit)-2 && pRe->aOp[i]==RE_OP_MATCH; i++){ + unsigned x = pRe->aArg[i]; + if( x<=127 ){ + pRe->zInit[j++] = (unsigned char)x; + }else if( x<=0xfff ){ + pRe->zInit[j++] = (unsigned char)(0xc0 | (x>>6)); + pRe->zInit[j++] = 0x80 | (x&0x3f); + }else if( x<=0xffff ){ + pRe->zInit[j++] = (unsigned char)(0xd0 | (x>>12)); + pRe->zInit[j++] = 0x80 | ((x>>6)&0x3f); + pRe->zInit[j++] = 0x80 | (x&0x3f); + }else{ + break; + } + } + if( j>0 && pRe->zInit[j-1]==0 ) j--; + pRe->nInit = j; + } + return pRe->zErr; } /* @@ -6672,40 +6672,40 @@ static const char *re_compile(ReCompiled **ppRe, const char *zIn, int noCase){ ** is implemented as regexp(B,A). */ static void re_sql_func( - sqlite3_context *context, - int argc, - sqlite3_value **argv + sqlite3_context *context, + int argc, + sqlite3_value **argv ){ - ReCompiled *pRe; /* Compiled regular expression */ - const char *zPattern; /* The regular expression */ - const unsigned char *zStr;/* String being searched */ - const char *zErr; /* Compile error message */ - int setAux = 0; /* True to invoke sqlite3_set_auxdata() */ - - (void)argc; /* Unused */ - pRe = sqlite3_get_auxdata(context, 0); - if( pRe==0 ){ - zPattern = (const char*)sqlite3_value_text(argv[0]); - if( zPattern==0 ) return; - zErr = re_compile(&pRe, zPattern, sqlite3_user_data(context)!=0); - if( zErr ){ - re_free(pRe); - sqlite3_result_error(context, zErr, -1); - return; - } - if( pRe==0 ){ - sqlite3_result_error_nomem(context); - return; - } - setAux = 1; - } - zStr = (const unsigned char*)sqlite3_value_text(argv[1]); - if( zStr!=0 ){ - sqlite3_result_int(context, re_match(pRe, zStr, -1)); + ReCompiled *pRe; /* Compiled regular expression */ + const char *zPattern; /* The regular expression */ + const unsigned char *zStr;/* String being searched */ + const char *zErr; /* Compile error message */ + int setAux = 0; /* True to invoke sqlite3_set_auxdata() */ + + (void)argc; /* Unused */ + pRe = sqlite3_get_auxdata(context, 0); + if( pRe==0 ){ + zPattern = (const char*)sqlite3_value_text(argv[0]); + if( zPattern==0 ) return; + zErr = re_compile(&pRe, zPattern, sqlite3_user_data(context)!=0); + if( zErr ){ + re_free(pRe); + sqlite3_result_error(context, zErr, -1); + return; } - if( setAux ){ - sqlite3_set_auxdata(context, 0, pRe, (void(*)(void*))re_free); + if( pRe==0 ){ + sqlite3_result_error_nomem(context); + return; } + setAux = 1; + } + zStr = (const unsigned char*)sqlite3_value_text(argv[1]); + if( zStr!=0 ){ + sqlite3_result_int(context, re_match(pRe, zStr, -1)); + } + if( setAux ){ + sqlite3_set_auxdata(context, 0, pRe, (void(*)(void*))re_free); + } } /* @@ -6716,22 +6716,22 @@ static void re_sql_func( #endif int sqlite3_regexp_init( - sqlite3 *db, - char **pzErrMsg, - const sqlite3_api_routines *pApi + sqlite3 *db, + char **pzErrMsg, + const sqlite3_api_routines *pApi ){ - int rc = SQLITE_OK; - SQLITE_EXTENSION_INIT2(pApi); - (void)pzErrMsg; /* Unused */ - rc = sqlite3_create_function(db, "regexp", 2, SQLITE_UTF8|SQLITE_INNOCUOUS, - 0, re_sql_func, 0, 0); - if( rc==SQLITE_OK ){ - /* The regexpi(PATTERN,STRING) function is a case-insensitive version + int rc = SQLITE_OK; + SQLITE_EXTENSION_INIT2(pApi); + (void)pzErrMsg; /* Unused */ + rc = sqlite3_create_function(db, "regexp", 2, SQLITE_UTF8|SQLITE_INNOCUOUS, + 0, re_sql_func, 0, 0); + if( rc==SQLITE_OK ){ + /* The regexpi(PATTERN,STRING) function is a case-insensitive version ** of regexp(PATTERN,STRING). */ - rc = sqlite3_create_function(db, "regexpi", 2, SQLITE_UTF8|SQLITE_INNOCUOUS, - (void*)db, re_sql_func, 0, 0); - } - return rc; + rc = sqlite3_create_function(db, "regexpi", 2, SQLITE_UTF8|SQLITE_INNOCUOUS, + (void*)db, re_sql_func, 0, 0); + } + return rc; } /************************* End ../ext/misc/regexp.c ********************/ @@ -6814,10 +6814,10 @@ typedef UINT16_TYPE u16; /* 2-byte unsigned integer */ /* ** Definitions for mode bitmasks S_IFDIR, S_IFREG and S_IFLNK. ** -** In some ways it would be better to obtain these values from system +** In some ways it would be better to obtain these values from system ** header files. But, the dependency is undesirable and (a) these ** have been stable for decades, (b) the values are part of POSIX and -** are also made explicit in [man stat], and (c) are part of the +** are also made explicit in [man stat], and (c) are part of the ** file format for zip archives. */ #ifndef S_IFDIR @@ -6830,8 +6830,8 @@ typedef UINT16_TYPE u16; /* 2-byte unsigned integer */ # define S_IFLNK 0120000 #endif -static const char ZIPFILE_SCHEMA[] = - "CREATE TABLE y(" +static const char ZIPFILE_SCHEMA[] = + "CREATE TABLE y(" "name PRIMARY KEY," /* 0: Name of file in zip archive */ "mode," /* 1: POSIX mode for file */ "mtime," /* 2: Last modification time (secs since 1970)*/ @@ -6840,7 +6840,7 @@ static const char ZIPFILE_SCHEMA[] = "data," /* 5: Uncompressed data */ "method," /* 6: Compression method (integer) */ "z HIDDEN" /* 7: Name of zip file */ - ") WITHOUT ROWID;"; + ") WITHOUT ROWID;"; #define ZIPFILE_F_COLUMN_IDX 7 /* Index of column "file" in the above */ #define ZIPFILE_BUFFER_SIZE (64*1024) @@ -6851,8 +6851,8 @@ static const char ZIPFILE_SCHEMA[] = ** ** ZIPFILE_NEWENTRY_MADEBY: ** Use this value for the "version-made-by" field in new zip file -** entries. The upper byte indicates "unix", and the lower byte -** indicates that the zip file matches pkzip specification 3.0. +** entries. The upper byte indicates "unix", and the lower byte +** indicates that the zip file matches pkzip specification 3.0. ** This is what info-zip seems to do. ** ** ZIPFILE_NEWENTRY_REQUIRED: @@ -6881,7 +6881,7 @@ static const char ZIPFILE_SCHEMA[] = #define ZIPFILE_SIGNATURE_EOCD 0x06054b50 /* -** The sizes of the fixed-size part of each of the three main data +** The sizes of the fixed-size part of each of the three main data ** structures in a zip archive. */ #define ZIPFILE_LFH_FIXED_SZ 30 @@ -6908,12 +6908,12 @@ static const char ZIPFILE_SCHEMA[] = */ typedef struct ZipfileEOCD ZipfileEOCD; struct ZipfileEOCD { - u16 iDisk; - u16 iFirstDisk; - u16 nEntry; - u16 nEntryTotal; - u32 nSize; - u32 iOffset; + u16 iDisk; + u16 iFirstDisk; + u16 nEntry; + u16 nEntryTotal; + u32 nSize; + u32 iOffset; }; /* @@ -6941,23 +6941,23 @@ struct ZipfileEOCD { */ typedef struct ZipfileCDS ZipfileCDS; struct ZipfileCDS { - u16 iVersionMadeBy; - u16 iVersionExtract; - u16 flags; - u16 iCompression; - u16 mTime; - u16 mDate; - u32 crc32; - u32 szCompressed; - u32 szUncompressed; - u16 nFile; - u16 nExtra; - u16 nComment; - u16 iDiskStart; - u16 iInternalAttr; - u32 iExternalAttr; - u32 iOffset; - char *zFile; /* Filename (sqlite3_malloc()) */ + u16 iVersionMadeBy; + u16 iVersionExtract; + u16 flags; + u16 iCompression; + u16 mTime; + u16 mDate; + u32 crc32; + u32 szCompressed; + u32 szUncompressed; + u16 nFile; + u16 nExtra; + u16 nComment; + u16 iDiskStart; + u16 iInternalAttr; + u32 iExternalAttr; + u32 iOffset; + char *zFile; /* Filename (sqlite3_malloc()) */ }; /* @@ -6974,68 +6974,68 @@ struct ZipfileCDS { *** uncompressed size 4 bytes *** file name length 2 bytes *** extra field length 2 bytes -*** +*** */ typedef struct ZipfileLFH ZipfileLFH; struct ZipfileLFH { - u16 iVersionExtract; - u16 flags; - u16 iCompression; - u16 mTime; - u16 mDate; - u32 crc32; - u32 szCompressed; - u32 szUncompressed; - u16 nFile; - u16 nExtra; + u16 iVersionExtract; + u16 flags; + u16 iCompression; + u16 mTime; + u16 mDate; + u32 crc32; + u32 szCompressed; + u32 szUncompressed; + u16 nFile; + u16 nExtra; }; typedef struct ZipfileEntry ZipfileEntry; struct ZipfileEntry { - ZipfileCDS cds; /* Parsed CDS record */ - u32 mUnixTime; /* Modification time, in UNIX format */ - u8 *aExtra; /* cds.nExtra+cds.nComment bytes of extra data */ - i64 iDataOff; /* Offset to data in file (if aData==0) */ - u8 *aData; /* cds.szCompressed bytes of compressed data */ - ZipfileEntry *pNext; /* Next element in in-memory CDS */ + ZipfileCDS cds; /* Parsed CDS record */ + u32 mUnixTime; /* Modification time, in UNIX format */ + u8 *aExtra; /* cds.nExtra+cds.nComment bytes of extra data */ + i64 iDataOff; /* Offset to data in file (if aData==0) */ + u8 *aData; /* cds.szCompressed bytes of compressed data */ + ZipfileEntry *pNext; /* Next element in in-memory CDS */ }; -/* +/* ** Cursor type for zipfile tables. */ typedef struct ZipfileCsr ZipfileCsr; struct ZipfileCsr { - sqlite3_vtab_cursor base; /* Base class - must be first */ - i64 iId; /* Cursor ID */ - u8 bEof; /* True when at EOF */ - u8 bNoop; /* If next xNext() call is no-op */ - - /* Used outside of write transactions */ - FILE *pFile; /* Zip file */ - i64 iNextOff; /* Offset of next record in central directory */ - ZipfileEOCD eocd; /* Parse of central directory record */ - - ZipfileEntry *pFreeEntry; /* Free this list when cursor is closed or reset */ - ZipfileEntry *pCurrent; /* Current entry */ - ZipfileCsr *pCsrNext; /* Next cursor on same virtual table */ + sqlite3_vtab_cursor base; /* Base class - must be first */ + i64 iId; /* Cursor ID */ + u8 bEof; /* True when at EOF */ + u8 bNoop; /* If next xNext() call is no-op */ + + /* Used outside of write transactions */ + FILE *pFile; /* Zip file */ + i64 iNextOff; /* Offset of next record in central directory */ + ZipfileEOCD eocd; /* Parse of central directory record */ + + ZipfileEntry *pFreeEntry; /* Free this list when cursor is closed or reset */ + ZipfileEntry *pCurrent; /* Current entry */ + ZipfileCsr *pCsrNext; /* Next cursor on same virtual table */ }; typedef struct ZipfileTab ZipfileTab; struct ZipfileTab { - sqlite3_vtab base; /* Base class - must be first */ - char *zFile; /* Zip file this table accesses (may be NULL) */ - sqlite3 *db; /* Host database connection */ - u8 *aBuffer; /* Temporary buffer used for various tasks */ - - ZipfileCsr *pCsrList; /* List of cursors */ - i64 iNextCsrid; - - /* The following are used by write transactions only */ - ZipfileEntry *pFirstEntry; /* Linked list of all files (if pWriteFd!=0) */ - ZipfileEntry *pLastEntry; /* Last element in pFirstEntry list */ - FILE *pWriteFd; /* File handle open on zip archive */ - i64 szCurrent; /* Current size of zip archive */ - i64 szOrig; /* Size of archive at start of transaction */ + sqlite3_vtab base; /* Base class - must be first */ + char *zFile; /* Zip file this table accesses (may be NULL) */ + sqlite3 *db; /* Host database connection */ + u8 *aBuffer; /* Temporary buffer used for various tasks */ + + ZipfileCsr *pCsrList; /* List of cursors */ + i64 iNextCsrid; + + /* The following are used by write transactions only */ + ZipfileEntry *pFirstEntry; /* Linked list of all files (if pWriteFd!=0) */ + ZipfileEntry *pLastEntry; /* Last element in pFirstEntry list */ + FILE *pWriteFd; /* File handle open on zip archive */ + i64 szCurrent; /* Current size of zip archive */ + i64 szOrig; /* Size of archive at start of transaction */ }; /* @@ -7043,13 +7043,13 @@ struct ZipfileTab { ** vprintf(zFmt, ...). */ static void zipfileCtxErrorMsg(sqlite3_context *ctx, const char *zFmt, ...){ - char *zMsg = 0; - va_list ap; - va_start(ap, zFmt); - zMsg = sqlite3_vmprintf(zFmt, ap); - sqlite3_result_error(ctx, zMsg, -1); - sqlite3_free(zMsg); - va_end(ap); + char *zMsg = 0; + va_list ap; + va_start(ap, zFmt); + zMsg = sqlite3_vmprintf(zFmt, ap); + sqlite3_result_error(ctx, zMsg, -1); + sqlite3_free(zMsg); + va_end(ap); } /* @@ -7057,42 +7057,42 @@ static void zipfileCtxErrorMsg(sqlite3_context *ctx, const char *zFmt, ...){ ** is not quoted, do nothing. */ static void zipfileDequote(char *zIn){ - char q = zIn[0]; - if( q=='"' || q=='\'' || q=='`' || q=='[' ){ - int iIn = 1; - int iOut = 0; - if( q=='[' ) q = ']'; - while( ALWAYS(zIn[iIn]) ){ - char c = zIn[iIn++]; - if( c==q && zIn[iIn++]!=q ) break; - zIn[iOut++] = c; - } - zIn[iOut] = '\0'; + char q = zIn[0]; + if( q=='"' || q=='\'' || q=='`' || q=='[' ){ + int iIn = 1; + int iOut = 0; + if( q=='[' ) q = ']'; + while( ALWAYS(zIn[iIn]) ){ + char c = zIn[iIn++]; + if( c==q && zIn[iIn++]!=q ) break; + zIn[iOut++] = c; } + zIn[iOut] = '\0'; + } } /* ** Construct a new ZipfileTab virtual table object. -** +** ** argv[0] -> module name ("zipfile") ** argv[1] -> database name ** argv[2] -> table name ** argv[...] -> "column name" and other module argument fields. */ static int zipfileConnect( - sqlite3 *db, - void *pAux, - int argc, const char *const*argv, - sqlite3_vtab **ppVtab, - char **pzErr + sqlite3 *db, + void *pAux, + int argc, const char *const*argv, + sqlite3_vtab **ppVtab, + char **pzErr ){ - int nByte = sizeof(ZipfileTab) + ZIPFILE_BUFFER_SIZE; - int nFile = 0; - const char *zFile = 0; - ZipfileTab *pNew = 0; - int rc; + int nByte = sizeof(ZipfileTab) + ZIPFILE_BUFFER_SIZE; + int nFile = 0; + const char *zFile = 0; + ZipfileTab *pNew = 0; + int rc; - /* If the table name is not "zipfile", require that the argument be + /* If the table name is not "zipfile", require that the argument be ** specified. This stops zipfile tables from being created as: ** ** CREATE VIRTUAL TABLE zzz USING zipfile(); @@ -7101,92 +7101,92 @@ static int zipfileConnect( ** ** CREATE VIRTUAL TABLE zipfile USING zipfile(); */ - assert( 0==sqlite3_stricmp(argv[0], "zipfile") ); - if( (0!=sqlite3_stricmp(argv[2], "zipfile") && argc<4) || argc>4 ){ - *pzErr = sqlite3_mprintf("zipfile constructor requires one argument"); - return SQLITE_ERROR; - } + assert( 0==sqlite3_stricmp(argv[0], "zipfile") ); + if( (0!=sqlite3_stricmp(argv[2], "zipfile") && argc<4) || argc>4 ){ + *pzErr = sqlite3_mprintf("zipfile constructor requires one argument"); + return SQLITE_ERROR; + } - if( argc>3 ){ - zFile = argv[3]; - nFile = (int)strlen(zFile)+1; - } + if( argc>3 ){ + zFile = argv[3]; + nFile = (int)strlen(zFile)+1; + } - rc = sqlite3_declare_vtab(db, ZIPFILE_SCHEMA); - if( rc==SQLITE_OK ){ - pNew = (ZipfileTab*)sqlite3_malloc64((sqlite3_int64)nByte+nFile); - if( pNew==0 ) return SQLITE_NOMEM; - memset(pNew, 0, nByte+nFile); - pNew->db = db; - pNew->aBuffer = (u8*)&pNew[1]; - if( zFile ){ - pNew->zFile = (char*)&pNew->aBuffer[ZIPFILE_BUFFER_SIZE]; - memcpy(pNew->zFile, zFile, nFile); - zipfileDequote(pNew->zFile); - } + rc = sqlite3_declare_vtab(db, ZIPFILE_SCHEMA); + if( rc==SQLITE_OK ){ + pNew = (ZipfileTab*)sqlite3_malloc64((sqlite3_int64)nByte+nFile); + if( pNew==0 ) return SQLITE_NOMEM; + memset(pNew, 0, nByte+nFile); + pNew->db = db; + pNew->aBuffer = (u8*)&pNew[1]; + if( zFile ){ + pNew->zFile = (char*)&pNew->aBuffer[ZIPFILE_BUFFER_SIZE]; + memcpy(pNew->zFile, zFile, nFile); + zipfileDequote(pNew->zFile); } - sqlite3_vtab_config(db, SQLITE_VTAB_DIRECTONLY); - *ppVtab = (sqlite3_vtab*)pNew; - return rc; + } + sqlite3_vtab_config(db, SQLITE_VTAB_DIRECTONLY); + *ppVtab = (sqlite3_vtab*)pNew; + return rc; } /* ** Free the ZipfileEntry structure indicated by the only argument. */ static void zipfileEntryFree(ZipfileEntry *p){ - if( p ){ - sqlite3_free(p->cds.zFile); - sqlite3_free(p); - } + if( p ){ + sqlite3_free(p->cds.zFile); + sqlite3_free(p); + } } /* -** Release resources that should be freed at the end of a write +** Release resources that should be freed at the end of a write ** transaction. */ static void zipfileCleanupTransaction(ZipfileTab *pTab){ - ZipfileEntry *pEntry; - ZipfileEntry *pNext; + ZipfileEntry *pEntry; + ZipfileEntry *pNext; - if( pTab->pWriteFd ){ - fclose(pTab->pWriteFd); - pTab->pWriteFd = 0; - } - for(pEntry=pTab->pFirstEntry; pEntry; pEntry=pNext){ - pNext = pEntry->pNext; - zipfileEntryFree(pEntry); - } - pTab->pFirstEntry = 0; - pTab->pLastEntry = 0; - pTab->szCurrent = 0; - pTab->szOrig = 0; + if( pTab->pWriteFd ){ + fclose(pTab->pWriteFd); + pTab->pWriteFd = 0; + } + for(pEntry=pTab->pFirstEntry; pEntry; pEntry=pNext){ + pNext = pEntry->pNext; + zipfileEntryFree(pEntry); + } + pTab->pFirstEntry = 0; + pTab->pLastEntry = 0; + pTab->szCurrent = 0; + pTab->szOrig = 0; } /* ** This method is the destructor for zipfile vtab objects. */ static int zipfileDisconnect(sqlite3_vtab *pVtab){ - zipfileCleanupTransaction((ZipfileTab*)pVtab); - sqlite3_free(pVtab); - return SQLITE_OK; + zipfileCleanupTransaction((ZipfileTab*)pVtab); + sqlite3_free(pVtab); + return SQLITE_OK; } /* ** Constructor for a new ZipfileCsr object. */ static int zipfileOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCsr){ - ZipfileTab *pTab = (ZipfileTab*)p; - ZipfileCsr *pCsr; - pCsr = sqlite3_malloc(sizeof(*pCsr)); - *ppCsr = (sqlite3_vtab_cursor*)pCsr; - if( pCsr==0 ){ - return SQLITE_NOMEM; - } - memset(pCsr, 0, sizeof(*pCsr)); - pCsr->iId = ++pTab->iNextCsrid; - pCsr->pCsrNext = pTab->pCsrList; - pTab->pCsrList = pCsr; - return SQLITE_OK; + ZipfileTab *pTab = (ZipfileTab*)p; + ZipfileCsr *pCsr; + pCsr = sqlite3_malloc(sizeof(*pCsr)); + *ppCsr = (sqlite3_vtab_cursor*)pCsr; + if( pCsr==0 ){ + return SQLITE_NOMEM; + } + memset(pCsr, 0, sizeof(*pCsr)); + pCsr->iId = ++pTab->iNextCsrid; + pCsr->pCsrNext = pTab->pCsrList; + pTab->pCsrList = pCsr; + return SQLITE_OK; } /* @@ -7194,38 +7194,38 @@ static int zipfileOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCsr){ ** by zipfileOpen(). */ static void zipfileResetCursor(ZipfileCsr *pCsr){ - ZipfileEntry *p; - ZipfileEntry *pNext; + ZipfileEntry *p; + ZipfileEntry *pNext; - pCsr->bEof = 0; - if( pCsr->pFile ){ - fclose(pCsr->pFile); - pCsr->pFile = 0; - zipfileEntryFree(pCsr->pCurrent); - pCsr->pCurrent = 0; - } + pCsr->bEof = 0; + if( pCsr->pFile ){ + fclose(pCsr->pFile); + pCsr->pFile = 0; + zipfileEntryFree(pCsr->pCurrent); + pCsr->pCurrent = 0; + } - for(p=pCsr->pFreeEntry; p; p=pNext){ - pNext = p->pNext; - zipfileEntryFree(p); - } + for(p=pCsr->pFreeEntry; p; p=pNext){ + pNext = p->pNext; + zipfileEntryFree(p); + } } /* ** Destructor for an ZipfileCsr. */ static int zipfileClose(sqlite3_vtab_cursor *cur){ - ZipfileCsr *pCsr = (ZipfileCsr*)cur; - ZipfileTab *pTab = (ZipfileTab*)(pCsr->base.pVtab); - ZipfileCsr **pp; - zipfileResetCursor(pCsr); + ZipfileCsr *pCsr = (ZipfileCsr*)cur; + ZipfileTab *pTab = (ZipfileTab*)(pCsr->base.pVtab); + ZipfileCsr **pp; + zipfileResetCursor(pCsr); - /* Remove this cursor from the ZipfileTab.pCsrList list. */ - for(pp=&pTab->pCsrList; *pp!=pCsr; pp=&((*pp)->pCsrNext)); - *pp = pCsr->pCsrNext; + /* Remove this cursor from the ZipfileTab.pCsrList list. */ + for(pp=&pTab->pCsrList; *pp!=pCsr; pp=&((*pp)->pCsrNext)); + *pp = pCsr->pCsrNext; - sqlite3_free(pCsr); - return SQLITE_OK; + sqlite3_free(pCsr); + return SQLITE_OK; } /* @@ -7233,24 +7233,24 @@ static int zipfileClose(sqlite3_vtab_cursor *cur){ ** pCsr to the results of vprintf(zFmt, ...). */ static void zipfileTableErr(ZipfileTab *pTab, const char *zFmt, ...){ - va_list ap; - va_start(ap, zFmt); - sqlite3_free(pTab->base.zErrMsg); - pTab->base.zErrMsg = sqlite3_vmprintf(zFmt, ap); - va_end(ap); + va_list ap; + va_start(ap, zFmt); + sqlite3_free(pTab->base.zErrMsg); + pTab->base.zErrMsg = sqlite3_vmprintf(zFmt, ap); + va_end(ap); } static void zipfileCursorErr(ZipfileCsr *pCsr, const char *zFmt, ...){ - va_list ap; - va_start(ap, zFmt); - sqlite3_free(pCsr->base.pVtab->zErrMsg); - pCsr->base.pVtab->zErrMsg = sqlite3_vmprintf(zFmt, ap); - va_end(ap); + va_list ap; + va_start(ap, zFmt); + sqlite3_free(pCsr->base.pVtab->zErrMsg); + pCsr->base.pVtab->zErrMsg = sqlite3_vmprintf(zFmt, ap); + va_end(ap); } /* ** Read nRead bytes of data from offset iOff of file pFile into buffer ** aRead[]. Return SQLITE_OK if successful, or an SQLite error code -** otherwise. +** otherwise. ** ** If an error does occur, output variable (*pzErrmsg) may be set to point ** to an English language error message. It is the responsibility of the @@ -7258,74 +7258,74 @@ static void zipfileCursorErr(ZipfileCsr *pCsr, const char *zFmt, ...){ ** sqlite3_free(). */ static int zipfileReadData( - FILE *pFile, /* Read from this file */ - u8 *aRead, /* Read into this buffer */ - int nRead, /* Number of bytes to read */ - i64 iOff, /* Offset to read from */ - char **pzErrmsg /* OUT: Error message (from sqlite3_malloc) */ + FILE *pFile, /* Read from this file */ + u8 *aRead, /* Read into this buffer */ + int nRead, /* Number of bytes to read */ + i64 iOff, /* Offset to read from */ + char **pzErrmsg /* OUT: Error message (from sqlite3_malloc) */ ){ - size_t n; - fseek(pFile, (long)iOff, SEEK_SET); - n = fread(aRead, 1, nRead, pFile); - if( (int)n!=nRead ){ - *pzErrmsg = sqlite3_mprintf("error in fread()"); - return SQLITE_ERROR; - } - return SQLITE_OK; + size_t n; + fseek(pFile, (long)iOff, SEEK_SET); + n = fread(aRead, 1, nRead, pFile); + if( (int)n!=nRead ){ + *pzErrmsg = sqlite3_mprintf("error in fread()"); + return SQLITE_ERROR; + } + return SQLITE_OK; } static int zipfileAppendData( - ZipfileTab *pTab, - const u8 *aWrite, - int nWrite + ZipfileTab *pTab, + const u8 *aWrite, + int nWrite ){ - if( nWrite>0 ){ - size_t n = nWrite; - fseek(pTab->pWriteFd, (long)pTab->szCurrent, SEEK_SET); - n = fwrite(aWrite, 1, nWrite, pTab->pWriteFd); - if( (int)n!=nWrite ){ - pTab->base.zErrMsg = sqlite3_mprintf("error in fwrite()"); - return SQLITE_ERROR; - } - pTab->szCurrent += nWrite; + if( nWrite>0 ){ + size_t n = nWrite; + fseek(pTab->pWriteFd, (long)pTab->szCurrent, SEEK_SET); + n = fwrite(aWrite, 1, nWrite, pTab->pWriteFd); + if( (int)n!=nWrite ){ + pTab->base.zErrMsg = sqlite3_mprintf("error in fwrite()"); + return SQLITE_ERROR; } - return SQLITE_OK; + pTab->szCurrent += nWrite; + } + return SQLITE_OK; } /* ** Read and return a 16-bit little-endian unsigned integer from buffer aBuf. */ static u16 zipfileGetU16(const u8 *aBuf){ - return (aBuf[1] << 8) + aBuf[0]; + return (aBuf[1] << 8) + aBuf[0]; } /* ** Read and return a 32-bit little-endian unsigned integer from buffer aBuf. */ static u32 zipfileGetU32(const u8 *aBuf){ - if( aBuf==0 ) return 0; - return ((u32)(aBuf[3]) << 24) - + ((u32)(aBuf[2]) << 16) - + ((u32)(aBuf[1]) << 8) - + ((u32)(aBuf[0]) << 0); + if( aBuf==0 ) return 0; + return ((u32)(aBuf[3]) << 24) + + ((u32)(aBuf[2]) << 16) + + ((u32)(aBuf[1]) << 8) + + ((u32)(aBuf[0]) << 0); } /* ** Write a 16-bit little endiate integer into buffer aBuf. */ static void zipfilePutU16(u8 *aBuf, u16 val){ - aBuf[0] = val & 0xFF; - aBuf[1] = (val>>8) & 0xFF; + aBuf[0] = val & 0xFF; + aBuf[1] = (val>>8) & 0xFF; } /* ** Write a 32-bit little endiate integer into buffer aBuf. */ static void zipfilePutU32(u8 *aBuf, u32 val){ - aBuf[0] = val & 0xFF; - aBuf[1] = (val>>8) & 0xFF; - aBuf[2] = (val>>16) & 0xFF; - aBuf[3] = (val>>24) & 0xFF; + aBuf[0] = val & 0xFF; + aBuf[1] = (val>>8) & 0xFF; + aBuf[2] = (val>>16) & 0xFF; + aBuf[3] = (val>>24) & 0xFF; } #define zipfileRead32(aBuf) ( aBuf+=4, zipfileGetU32(aBuf-4) ) @@ -7345,33 +7345,33 @@ static void zipfilePutU32(u8 *aBuf, u32 val){ ** if the record is not well-formed, or SQLITE_OK otherwise. */ static int zipfileReadCDS(u8 *aBuf, ZipfileCDS *pCDS){ - u8 *aRead = aBuf; - u32 sig = zipfileRead32(aRead); - int rc = SQLITE_OK; - if( sig!=ZIPFILE_SIGNATURE_CDS ){ - rc = SQLITE_ERROR; - }else{ - pCDS->iVersionMadeBy = zipfileRead16(aRead); - pCDS->iVersionExtract = zipfileRead16(aRead); - pCDS->flags = zipfileRead16(aRead); - pCDS->iCompression = zipfileRead16(aRead); - pCDS->mTime = zipfileRead16(aRead); - pCDS->mDate = zipfileRead16(aRead); - pCDS->crc32 = zipfileRead32(aRead); - pCDS->szCompressed = zipfileRead32(aRead); - pCDS->szUncompressed = zipfileRead32(aRead); - assert( aRead==&aBuf[ZIPFILE_CDS_NFILE_OFF] ); - pCDS->nFile = zipfileRead16(aRead); - pCDS->nExtra = zipfileRead16(aRead); - pCDS->nComment = zipfileRead16(aRead); - pCDS->iDiskStart = zipfileRead16(aRead); - pCDS->iInternalAttr = zipfileRead16(aRead); - pCDS->iExternalAttr = zipfileRead32(aRead); - pCDS->iOffset = zipfileRead32(aRead); - assert( aRead==&aBuf[ZIPFILE_CDS_FIXED_SZ] ); - } - - return rc; + u8 *aRead = aBuf; + u32 sig = zipfileRead32(aRead); + int rc = SQLITE_OK; + if( sig!=ZIPFILE_SIGNATURE_CDS ){ + rc = SQLITE_ERROR; + }else{ + pCDS->iVersionMadeBy = zipfileRead16(aRead); + pCDS->iVersionExtract = zipfileRead16(aRead); + pCDS->flags = zipfileRead16(aRead); + pCDS->iCompression = zipfileRead16(aRead); + pCDS->mTime = zipfileRead16(aRead); + pCDS->mDate = zipfileRead16(aRead); + pCDS->crc32 = zipfileRead32(aRead); + pCDS->szCompressed = zipfileRead32(aRead); + pCDS->szUncompressed = zipfileRead32(aRead); + assert( aRead==&aBuf[ZIPFILE_CDS_NFILE_OFF] ); + pCDS->nFile = zipfileRead16(aRead); + pCDS->nExtra = zipfileRead16(aRead); + pCDS->nComment = zipfileRead16(aRead); + pCDS->iDiskStart = zipfileRead16(aRead); + pCDS->iInternalAttr = zipfileRead16(aRead); + pCDS->iExternalAttr = zipfileRead32(aRead); + pCDS->iOffset = zipfileRead32(aRead); + assert( aRead==&aBuf[ZIPFILE_CDS_FIXED_SZ] ); + } + + return rc; } /* @@ -7379,28 +7379,28 @@ static int zipfileReadCDS(u8 *aBuf, ZipfileCDS *pCDS){ ** if the record is not well-formed, or SQLITE_OK otherwise. */ static int zipfileReadLFH( - u8 *aBuffer, - ZipfileLFH *pLFH + u8 *aBuffer, + ZipfileLFH *pLFH ){ - u8 *aRead = aBuffer; - int rc = SQLITE_OK; + u8 *aRead = aBuffer; + int rc = SQLITE_OK; - u32 sig = zipfileRead32(aRead); - if( sig!=ZIPFILE_SIGNATURE_LFH ){ - rc = SQLITE_ERROR; - }else{ - pLFH->iVersionExtract = zipfileRead16(aRead); - pLFH->flags = zipfileRead16(aRead); - pLFH->iCompression = zipfileRead16(aRead); - pLFH->mTime = zipfileRead16(aRead); - pLFH->mDate = zipfileRead16(aRead); - pLFH->crc32 = zipfileRead32(aRead); - pLFH->szCompressed = zipfileRead32(aRead); - pLFH->szUncompressed = zipfileRead32(aRead); - pLFH->nFile = zipfileRead16(aRead); - pLFH->nExtra = zipfileRead16(aRead); - } - return rc; + u32 sig = zipfileRead32(aRead); + if( sig!=ZIPFILE_SIGNATURE_LFH ){ + rc = SQLITE_ERROR; + }else{ + pLFH->iVersionExtract = zipfileRead16(aRead); + pLFH->flags = zipfileRead16(aRead); + pLFH->iCompression = zipfileRead16(aRead); + pLFH->mTime = zipfileRead16(aRead); + pLFH->mDate = zipfileRead16(aRead); + pLFH->crc32 = zipfileRead32(aRead); + pLFH->szCompressed = zipfileRead32(aRead); + pLFH->szUncompressed = zipfileRead32(aRead); + pLFH->nFile = zipfileRead16(aRead); + pLFH->nExtra = zipfileRead16(aRead); + } + return rc; } @@ -7420,28 +7420,28 @@ static int zipfileReadLFH( ** Data N bytes */ static int zipfileScanExtra(u8 *aExtra, int nExtra, u32 *pmTime){ - int ret = 0; - u8 *p = aExtra; - u8 *pEnd = &aExtra[nExtra]; - - while( p modtime is present */ - *pmTime = zipfileGetU32(&p[1]); - ret = 1; - } - break; - } - } + int ret = 0; + u8 *p = aExtra; + u8 *pEnd = &aExtra[nExtra]; + + while( p modtime is present */ + *pmTime = zipfileGetU32(&p[1]); + ret = 1; + } + break; + } } - return ret; + + p += nByte; + } + return ret; } /* @@ -7458,29 +7458,29 @@ static int zipfileScanExtra(u8 *aExtra, int nExtra, u32 *pmTime){ ** File modification date: ** Bits 00-04: day ** Bits 05-08: month (1-12) -** Bits 09-15: years from 1980 +** Bits 09-15: years from 1980 ** ** https://msdn.microsoft.com/en-us/library/9kkf9tah.aspx */ static u32 zipfileMtime(ZipfileCDS *pCDS){ - int Y,M,D,X1,X2,A,B,sec,min,hr; - i64 JDsec; - Y = (1980 + ((pCDS->mDate >> 9) & 0x7F)); - M = ((pCDS->mDate >> 5) & 0x0F); - D = (pCDS->mDate & 0x1F); - sec = (pCDS->mTime & 0x1F)*2; - min = (pCDS->mTime >> 5) & 0x3F; - hr = (pCDS->mTime >> 11) & 0x1F; - if( M<=2 ){ - Y--; - M += 12; - } - X1 = 36525*(Y+4716)/100; - X2 = 306001*(M+1)/10000; - A = Y/100; - B = 2 - A + (A/4); - JDsec = (i64)((X1 + X2 + D + B - 1524.5)*86400) + hr*3600 + min*60 + sec; - return (u32)(JDsec - (i64)24405875*(i64)8640); + int Y,M,D,X1,X2,A,B,sec,min,hr; + i64 JDsec; + Y = (1980 + ((pCDS->mDate >> 9) & 0x7F)); + M = ((pCDS->mDate >> 5) & 0x0F); + D = (pCDS->mDate & 0x1F); + sec = (pCDS->mTime & 0x1F)*2; + min = (pCDS->mTime >> 5) & 0x3F; + hr = (pCDS->mTime >> 11) & 0x1F; + if( M<=2 ){ + Y--; + M += 12; + } + X1 = 36525*(Y+4716)/100; + X2 = 306001*(M+1)/10000; + A = Y/100; + B = 2 - A + (A/4); + JDsec = (i64)((X1 + X2 + D + B - 1524.5)*86400) + hr*3600 + min*60 + sec; + return (u32)(JDsec - (i64)24405875*(i64)8640); } /* @@ -7489,40 +7489,40 @@ static u32 zipfileMtime(ZipfileCDS *pCDS){ ** to the UNIX timestamp value passed as the second. */ static void zipfileMtimeToDos(ZipfileCDS *pCds, u32 mUnixTime){ - /* Convert unix timestamp to JD (2440588 is noon on 1/1/1970) */ - i64 JD = (i64)2440588 + mUnixTime / (24*60*60); - - int A, B, C, D, E; - int yr, mon, day; - int hr, min, sec; - - A = (int)((JD - 1867216.25)/36524.25); - A = (int)(JD + 1 + A - (A/4)); - B = A + 1524; - C = (int)((B - 122.1)/365.25); - D = (36525*(C&32767))/100; - E = (int)((B-D)/30.6001); - - day = B - D - (int)(30.6001*E); - mon = (E<14 ? E-1 : E-13); - yr = mon>2 ? C-4716 : C-4715; - - hr = (mUnixTime % (24*60*60)) / (60*60); - min = (mUnixTime % (60*60)) / 60; - sec = (mUnixTime % 60); - - if( yr>=1980 ){ - pCds->mDate = (u16)(day + (mon << 5) + ((yr-1980) << 9)); - pCds->mTime = (u16)(sec/2 + (min<<5) + (hr<<11)); - }else{ - pCds->mDate = pCds->mTime = 0; - } + /* Convert unix timestamp to JD (2440588 is noon on 1/1/1970) */ + i64 JD = (i64)2440588 + mUnixTime / (24*60*60); - assert( mUnixTime<315507600 - || mUnixTime==zipfileMtime(pCds) - || ((mUnixTime % 2) && mUnixTime-1==zipfileMtime(pCds)) - /* || (mUnixTime % 2) */ - ); + int A, B, C, D, E; + int yr, mon, day; + int hr, min, sec; + + A = (int)((JD - 1867216.25)/36524.25); + A = (int)(JD + 1 + A - (A/4)); + B = A + 1524; + C = (int)((B - 122.1)/365.25); + D = (36525*(C&32767))/100; + E = (int)((B-D)/30.6001); + + day = B - D - (int)(30.6001*E); + mon = (E<14 ? E-1 : E-13); + yr = mon>2 ? C-4716 : C-4715; + + hr = (mUnixTime % (24*60*60)) / (60*60); + min = (mUnixTime % (60*60)) / 60; + sec = (mUnixTime % 60); + + if( yr>=1980 ){ + pCds->mDate = (u16)(day + (mon << 5) + ((yr-1980) << 9)); + pCds->mTime = (u16)(sec/2 + (min<<5) + (hr<<11)); + }else{ + pCds->mDate = pCds->mTime = 0; + } + + assert( mUnixTime<315507600 + || mUnixTime==zipfileMtime(pCds) + || ((mUnixTime % 2) && mUnixTime-1==zipfileMtime(pCds)) + /* || (mUnixTime % 2) */ + ); } /* @@ -7537,138 +7537,138 @@ static void zipfileMtimeToDos(ZipfileCDS *pCds, u32 mUnixTime){ ** final value of (*ppEntry) undefined. */ static int zipfileGetEntry( - ZipfileTab *pTab, /* Store any error message here */ - const u8 *aBlob, /* Pointer to in-memory file image */ - int nBlob, /* Size of aBlob[] in bytes */ - FILE *pFile, /* If aBlob==0, read from this file */ - i64 iOff, /* Offset of CDS record */ - ZipfileEntry **ppEntry /* OUT: Pointer to new object */ + ZipfileTab *pTab, /* Store any error message here */ + const u8 *aBlob, /* Pointer to in-memory file image */ + int nBlob, /* Size of aBlob[] in bytes */ + FILE *pFile, /* If aBlob==0, read from this file */ + i64 iOff, /* Offset of CDS record */ + ZipfileEntry **ppEntry /* OUT: Pointer to new object */ ){ - u8 *aRead; - char **pzErr = &pTab->base.zErrMsg; - int rc = SQLITE_OK; + u8 *aRead; + char **pzErr = &pTab->base.zErrMsg; + int rc = SQLITE_OK; + + if( aBlob==0 ){ + aRead = pTab->aBuffer; + rc = zipfileReadData(pFile, aRead, ZIPFILE_CDS_FIXED_SZ, iOff, pzErr); + }else{ + aRead = (u8*)&aBlob[iOff]; + } + + if( rc==SQLITE_OK ){ + sqlite3_int64 nAlloc; + ZipfileEntry *pNew; + + int nFile = zipfileGetU16(&aRead[ZIPFILE_CDS_NFILE_OFF]); + int nExtra = zipfileGetU16(&aRead[ZIPFILE_CDS_NFILE_OFF+2]); + nExtra += zipfileGetU16(&aRead[ZIPFILE_CDS_NFILE_OFF+4]); + + nAlloc = sizeof(ZipfileEntry) + nExtra; + if( aBlob ){ + nAlloc += zipfileGetU32(&aRead[ZIPFILE_CDS_SZCOMPRESSED_OFF]); + } - if( aBlob==0 ){ - aRead = pTab->aBuffer; - rc = zipfileReadData(pFile, aRead, ZIPFILE_CDS_FIXED_SZ, iOff, pzErr); + pNew = (ZipfileEntry*)sqlite3_malloc64(nAlloc); + if( pNew==0 ){ + rc = SQLITE_NOMEM; }else{ - aRead = (u8*)&aBlob[iOff]; + memset(pNew, 0, sizeof(ZipfileEntry)); + rc = zipfileReadCDS(aRead, &pNew->cds); + if( rc!=SQLITE_OK ){ + *pzErr = sqlite3_mprintf("failed to read CDS at offset %lld", iOff); + }else if( aBlob==0 ){ + rc = zipfileReadData( + pFile, aRead, nExtra+nFile, iOff+ZIPFILE_CDS_FIXED_SZ, pzErr + ); + }else{ + aRead = (u8*)&aBlob[iOff + ZIPFILE_CDS_FIXED_SZ]; + } } if( rc==SQLITE_OK ){ - sqlite3_int64 nAlloc; - ZipfileEntry *pNew; - - int nFile = zipfileGetU16(&aRead[ZIPFILE_CDS_NFILE_OFF]); - int nExtra = zipfileGetU16(&aRead[ZIPFILE_CDS_NFILE_OFF+2]); - nExtra += zipfileGetU16(&aRead[ZIPFILE_CDS_NFILE_OFF+4]); - - nAlloc = sizeof(ZipfileEntry) + nExtra; - if( aBlob ){ - nAlloc += zipfileGetU32(&aRead[ZIPFILE_CDS_SZCOMPRESSED_OFF]); - } - - pNew = (ZipfileEntry*)sqlite3_malloc64(nAlloc); - if( pNew==0 ){ - rc = SQLITE_NOMEM; - }else{ - memset(pNew, 0, sizeof(ZipfileEntry)); - rc = zipfileReadCDS(aRead, &pNew->cds); - if( rc!=SQLITE_OK ){ - *pzErr = sqlite3_mprintf("failed to read CDS at offset %lld", iOff); - }else if( aBlob==0 ){ - rc = zipfileReadData( - pFile, aRead, nExtra+nFile, iOff+ZIPFILE_CDS_FIXED_SZ, pzErr - ); - }else{ - aRead = (u8*)&aBlob[iOff + ZIPFILE_CDS_FIXED_SZ]; - } - } - - if( rc==SQLITE_OK ){ - u32 *pt = &pNew->mUnixTime; - pNew->cds.zFile = sqlite3_mprintf("%.*s", nFile, aRead); - pNew->aExtra = (u8*)&pNew[1]; - memcpy(pNew->aExtra, &aRead[nFile], nExtra); - if( pNew->cds.zFile==0 ){ - rc = SQLITE_NOMEM; - }else if( 0==zipfileScanExtra(&aRead[nFile], pNew->cds.nExtra, pt) ){ - pNew->mUnixTime = zipfileMtime(&pNew->cds); - } - } - - if( rc==SQLITE_OK ){ - static const int szFix = ZIPFILE_LFH_FIXED_SZ; - ZipfileLFH lfh; - if( pFile ){ - rc = zipfileReadData(pFile, aRead, szFix, pNew->cds.iOffset, pzErr); - }else{ - aRead = (u8*)&aBlob[pNew->cds.iOffset]; - } + u32 *pt = &pNew->mUnixTime; + pNew->cds.zFile = sqlite3_mprintf("%.*s", nFile, aRead); + pNew->aExtra = (u8*)&pNew[1]; + memcpy(pNew->aExtra, &aRead[nFile], nExtra); + if( pNew->cds.zFile==0 ){ + rc = SQLITE_NOMEM; + }else if( 0==zipfileScanExtra(&aRead[nFile], pNew->cds.nExtra, pt) ){ + pNew->mUnixTime = zipfileMtime(&pNew->cds); + } + } - if( rc==SQLITE_OK ) rc = zipfileReadLFH(aRead, &lfh); - if( rc==SQLITE_OK ){ - pNew->iDataOff = pNew->cds.iOffset + ZIPFILE_LFH_FIXED_SZ; - pNew->iDataOff += lfh.nFile + lfh.nExtra; - if( aBlob && pNew->cds.szCompressed ){ - pNew->aData = &pNew->aExtra[nExtra]; - memcpy(pNew->aData, &aBlob[pNew->iDataOff], pNew->cds.szCompressed); - } - }else{ - *pzErr = sqlite3_mprintf("failed to read LFH at offset %d", - (int)pNew->cds.iOffset - ); - } - } + if( rc==SQLITE_OK ){ + static const int szFix = ZIPFILE_LFH_FIXED_SZ; + ZipfileLFH lfh; + if( pFile ){ + rc = zipfileReadData(pFile, aRead, szFix, pNew->cds.iOffset, pzErr); + }else{ + aRead = (u8*)&aBlob[pNew->cds.iOffset]; + } + + if( rc==SQLITE_OK ) rc = zipfileReadLFH(aRead, &lfh); + if( rc==SQLITE_OK ){ + pNew->iDataOff = pNew->cds.iOffset + ZIPFILE_LFH_FIXED_SZ; + pNew->iDataOff += lfh.nFile + lfh.nExtra; + if( aBlob && pNew->cds.szCompressed ){ + pNew->aData = &pNew->aExtra[nExtra]; + memcpy(pNew->aData, &aBlob[pNew->iDataOff], pNew->cds.szCompressed); + } + }else{ + *pzErr = sqlite3_mprintf("failed to read LFH at offset %d", + (int)pNew->cds.iOffset + ); + } + } - if( rc!=SQLITE_OK ){ - zipfileEntryFree(pNew); - }else{ - *ppEntry = pNew; - } + if( rc!=SQLITE_OK ){ + zipfileEntryFree(pNew); + }else{ + *ppEntry = pNew; } + } - return rc; + return rc; } /* ** Advance an ZipfileCsr to its next row of output. */ static int zipfileNext(sqlite3_vtab_cursor *cur){ - ZipfileCsr *pCsr = (ZipfileCsr*)cur; - int rc = SQLITE_OK; - - if( pCsr->pFile ){ - i64 iEof = pCsr->eocd.iOffset + pCsr->eocd.nSize; - zipfileEntryFree(pCsr->pCurrent); - pCsr->pCurrent = 0; - if( pCsr->iNextOff>=iEof ){ - pCsr->bEof = 1; - }else{ - ZipfileEntry *p = 0; - ZipfileTab *pTab = (ZipfileTab*)(cur->pVtab); - rc = zipfileGetEntry(pTab, 0, 0, pCsr->pFile, pCsr->iNextOff, &p); - if( rc==SQLITE_OK ){ - pCsr->iNextOff += ZIPFILE_CDS_FIXED_SZ; - pCsr->iNextOff += (int)p->cds.nExtra + p->cds.nFile + p->cds.nComment; - } - pCsr->pCurrent = p; - } + ZipfileCsr *pCsr = (ZipfileCsr*)cur; + int rc = SQLITE_OK; + + if( pCsr->pFile ){ + i64 iEof = pCsr->eocd.iOffset + pCsr->eocd.nSize; + zipfileEntryFree(pCsr->pCurrent); + pCsr->pCurrent = 0; + if( pCsr->iNextOff>=iEof ){ + pCsr->bEof = 1; }else{ - if( !pCsr->bNoop ){ - pCsr->pCurrent = pCsr->pCurrent->pNext; - } - if( pCsr->pCurrent==0 ){ - pCsr->bEof = 1; - } + ZipfileEntry *p = 0; + ZipfileTab *pTab = (ZipfileTab*)(cur->pVtab); + rc = zipfileGetEntry(pTab, 0, 0, pCsr->pFile, pCsr->iNextOff, &p); + if( rc==SQLITE_OK ){ + pCsr->iNextOff += ZIPFILE_CDS_FIXED_SZ; + pCsr->iNextOff += (int)p->cds.nExtra + p->cds.nFile + p->cds.nComment; + } + pCsr->pCurrent = p; + } + }else{ + if( !pCsr->bNoop ){ + pCsr->pCurrent = pCsr->pCurrent->pNext; } + if( pCsr->pCurrent==0 ){ + pCsr->bEof = 1; + } + } - pCsr->bNoop = 0; - return rc; + pCsr->bNoop = 0; + return rc; } -static void zipfileFree(void *p) { - sqlite3_free(p); +static void zipfileFree(void *p) { + sqlite3_free(p); } /* @@ -7679,46 +7679,46 @@ static void zipfileFree(void *p) { ** If an error occurs, an error code is left in pCtx instead. */ static void zipfileInflate( - sqlite3_context *pCtx, /* Store result here */ - const u8 *aIn, /* Compressed data */ - int nIn, /* Size of buffer aIn[] in bytes */ - int nOut /* Expected output size */ + sqlite3_context *pCtx, /* Store result here */ + const u8 *aIn, /* Compressed data */ + int nIn, /* Size of buffer aIn[] in bytes */ + int nOut /* Expected output size */ ){ - u8 *aRes = sqlite3_malloc(nOut); - if( aRes==0 ){ - sqlite3_result_error_nomem(pCtx); + u8 *aRes = sqlite3_malloc(nOut); + if( aRes==0 ){ + sqlite3_result_error_nomem(pCtx); + }else{ + int err; + z_stream str; + memset(&str, 0, sizeof(str)); + + str.next_in = (Byte*)aIn; + str.avail_in = nIn; + str.next_out = (Byte*)aRes; + str.avail_out = nOut; + + err = inflateInit2(&str, -15); + if( err!=Z_OK ){ + zipfileCtxErrorMsg(pCtx, "inflateInit2() failed (%d)", err); }else{ - int err; - z_stream str; - memset(&str, 0, sizeof(str)); - - str.next_in = (Byte*)aIn; - str.avail_in = nIn; - str.next_out = (Byte*)aRes; - str.avail_out = nOut; - - err = inflateInit2(&str, -15); - if( err!=Z_OK ){ - zipfileCtxErrorMsg(pCtx, "inflateInit2() failed (%d)", err); - }else{ - err = inflate(&str, Z_NO_FLUSH); - if( err!=Z_STREAM_END ){ - zipfileCtxErrorMsg(pCtx, "inflate() failed (%d)", err); - }else{ - sqlite3_result_blob(pCtx, aRes, nOut, zipfileFree); - aRes = 0; - } - } - sqlite3_free(aRes); - inflateEnd(&str); + err = inflate(&str, Z_NO_FLUSH); + if( err!=Z_STREAM_END ){ + zipfileCtxErrorMsg(pCtx, "inflate() failed (%d)", err); + }else{ + sqlite3_result_blob(pCtx, aRes, nOut, zipfileFree); + aRes = 0; + } } + sqlite3_free(aRes); + inflateEnd(&str); + } } /* ** Buffer aIn (size nIn bytes) contains uncompressed data. This function ** compresses it and sets (*ppOut) to point to a buffer containing the ** compressed data. The caller is responsible for eventually calling -** sqlite3_free() to release buffer (*ppOut). Before returning, (*pnOut) +** sqlite3_free() to release buffer (*ppOut). Before returning, (*pnOut) ** is set to the size of buffer (*ppOut) in bytes. ** ** If no error occurs, SQLITE_OK is returned. Otherwise, an SQLite error @@ -7727,41 +7727,41 @@ static void zipfileInflate( ** case. */ static int zipfileDeflate( - const u8 *aIn, int nIn, /* Input */ - u8 **ppOut, int *pnOut, /* Output */ - char **pzErr /* OUT: Error message */ + const u8 *aIn, int nIn, /* Input */ + u8 **ppOut, int *pnOut, /* Output */ + char **pzErr /* OUT: Error message */ ){ - int rc = SQLITE_OK; - sqlite3_int64 nAlloc; - z_stream str; - u8 *aOut; - - memset(&str, 0, sizeof(str)); - str.next_in = (Bytef*)aIn; - str.avail_in = nIn; - deflateInit2(&str, 9, Z_DEFLATED, -15, 8, Z_DEFAULT_STRATEGY); - - nAlloc = deflateBound(&str, nIn); - aOut = (u8*)sqlite3_malloc64(nAlloc); - if( aOut==0 ){ - rc = SQLITE_NOMEM; + int rc = SQLITE_OK; + sqlite3_int64 nAlloc; + z_stream str; + u8 *aOut; + + memset(&str, 0, sizeof(str)); + str.next_in = (Bytef*)aIn; + str.avail_in = nIn; + deflateInit2(&str, 9, Z_DEFLATED, -15, 8, Z_DEFAULT_STRATEGY); + + nAlloc = deflateBound(&str, nIn); + aOut = (u8*)sqlite3_malloc64(nAlloc); + if( aOut==0 ){ + rc = SQLITE_NOMEM; + }else{ + int res; + str.next_out = aOut; + str.avail_out = nAlloc; + res = deflate(&str, Z_FINISH); + if( res==Z_STREAM_END ){ + *ppOut = aOut; + *pnOut = (int)str.total_out; }else{ - int res; - str.next_out = aOut; - str.avail_out = nAlloc; - res = deflate(&str, Z_FINISH); - if( res==Z_STREAM_END ){ - *ppOut = aOut; - *pnOut = (int)str.total_out; - }else{ - sqlite3_free(aOut); - *pzErr = sqlite3_mprintf("zipfile: deflate() error"); - rc = SQLITE_ERROR; - } - deflateEnd(&str); + sqlite3_free(aOut); + *pzErr = sqlite3_mprintf("zipfile: deflate() error"); + rc = SQLITE_ERROR; } + deflateEnd(&str); + } - return rc; + return rc; } @@ -7770,95 +7770,95 @@ static int zipfileDeflate( ** is currently pointing. */ static int zipfileColumn( - sqlite3_vtab_cursor *cur, /* The cursor */ - sqlite3_context *ctx, /* First argument to sqlite3_result_...() */ - int i /* Which column to return */ + sqlite3_vtab_cursor *cur, /* The cursor */ + sqlite3_context *ctx, /* First argument to sqlite3_result_...() */ + int i /* Which column to return */ ){ - ZipfileCsr *pCsr = (ZipfileCsr*)cur; - ZipfileCDS *pCDS = &pCsr->pCurrent->cds; - int rc = SQLITE_OK; - switch( i ){ - case 0: /* name */ - sqlite3_result_text(ctx, pCDS->zFile, -1, SQLITE_TRANSIENT); - break; - case 1: /* mode */ - /* TODO: Whether or not the following is correct surely depends on + ZipfileCsr *pCsr = (ZipfileCsr*)cur; + ZipfileCDS *pCDS = &pCsr->pCurrent->cds; + int rc = SQLITE_OK; + switch( i ){ + case 0: /* name */ + sqlite3_result_text(ctx, pCDS->zFile, -1, SQLITE_TRANSIENT); + break; + case 1: /* mode */ + /* TODO: Whether or not the following is correct surely depends on ** the platform on which the archive was created. */ - sqlite3_result_int(ctx, pCDS->iExternalAttr >> 16); - break; - case 2: { /* mtime */ - sqlite3_result_int64(ctx, pCsr->pCurrent->mUnixTime); - break; - } - case 3: { /* sz */ - if( sqlite3_vtab_nochange(ctx)==0 ){ - sqlite3_result_int64(ctx, pCDS->szUncompressed); + sqlite3_result_int(ctx, pCDS->iExternalAttr >> 16); + break; + case 2: { /* mtime */ + sqlite3_result_int64(ctx, pCsr->pCurrent->mUnixTime); + break; + } + case 3: { /* sz */ + if( sqlite3_vtab_nochange(ctx)==0 ){ + sqlite3_result_int64(ctx, pCDS->szUncompressed); + } + break; + } + case 4: /* rawdata */ + if( sqlite3_vtab_nochange(ctx) ) break; + case 5: { /* data */ + if( i==4 || pCDS->iCompression==0 || pCDS->iCompression==8 ){ + int sz = pCDS->szCompressed; + int szFinal = pCDS->szUncompressed; + if( szFinal>0 ){ + u8 *aBuf; + u8 *aFree = 0; + if( pCsr->pCurrent->aData ){ + aBuf = pCsr->pCurrent->aData; + }else{ + aBuf = aFree = sqlite3_malloc64(sz); + if( aBuf==0 ){ + rc = SQLITE_NOMEM; + }else{ + FILE *pFile = pCsr->pFile; + if( pFile==0 ){ + pFile = ((ZipfileTab*)(pCsr->base.pVtab))->pWriteFd; + } + rc = zipfileReadData(pFile, aBuf, sz, pCsr->pCurrent->iDataOff, + &pCsr->base.pVtab->zErrMsg + ); + } + } + if( rc==SQLITE_OK ){ + if( i==5 && pCDS->iCompression ){ + zipfileInflate(ctx, aBuf, sz, szFinal); + }else{ + sqlite3_result_blob(ctx, aBuf, sz, SQLITE_TRANSIENT); } - break; - } - case 4: /* rawdata */ - if( sqlite3_vtab_nochange(ctx) ) break; - case 5: { /* data */ - if( i==4 || pCDS->iCompression==0 || pCDS->iCompression==8 ){ - int sz = pCDS->szCompressed; - int szFinal = pCDS->szUncompressed; - if( szFinal>0 ){ - u8 *aBuf; - u8 *aFree = 0; - if( pCsr->pCurrent->aData ){ - aBuf = pCsr->pCurrent->aData; - }else{ - aBuf = aFree = sqlite3_malloc64(sz); - if( aBuf==0 ){ - rc = SQLITE_NOMEM; - }else{ - FILE *pFile = pCsr->pFile; - if( pFile==0 ){ - pFile = ((ZipfileTab*)(pCsr->base.pVtab))->pWriteFd; - } - rc = zipfileReadData(pFile, aBuf, sz, pCsr->pCurrent->iDataOff, - &pCsr->base.pVtab->zErrMsg - ); - } - } - if( rc==SQLITE_OK ){ - if( i==5 && pCDS->iCompression ){ - zipfileInflate(ctx, aBuf, sz, szFinal); - }else{ - sqlite3_result_blob(ctx, aBuf, sz, SQLITE_TRANSIENT); - } - } - sqlite3_free(aFree); - }else{ - /* Figure out if this is a directory or a zero-sized file. Consider + } + sqlite3_free(aFree); + }else{ + /* Figure out if this is a directory or a zero-sized file. Consider ** it to be a directory either if the mode suggests so, or if ** the final character in the name is '/'. */ - u32 mode = pCDS->iExternalAttr >> 16; - if( !(mode & S_IFDIR) && pCDS->zFile[pCDS->nFile-1]!='/' ){ - sqlite3_result_blob(ctx, "", 0, SQLITE_STATIC); - } - } - } - break; + u32 mode = pCDS->iExternalAttr >> 16; + if( !(mode & S_IFDIR) && pCDS->zFile[pCDS->nFile-1]!='/' ){ + sqlite3_result_blob(ctx, "", 0, SQLITE_STATIC); + } } - case 6: /* method */ - sqlite3_result_int(ctx, pCDS->iCompression); - break; - default: /* z */ - assert( i==7 ); - sqlite3_result_int64(ctx, pCsr->iId); - break; + } + break; } + case 6: /* method */ + sqlite3_result_int(ctx, pCDS->iCompression); + break; + default: /* z */ + assert( i==7 ); + sqlite3_result_int64(ctx, pCsr->iId); + break; + } - return rc; + return rc; } /* ** Return TRUE if the cursor is at EOF. */ static int zipfileEof(sqlite3_vtab_cursor *cur){ - ZipfileCsr *pCsr = (ZipfileCsr*)cur; - return pCsr->bEof; + ZipfileCsr *pCsr = (ZipfileCsr*)cur; + return pCsr->bEof; } /* @@ -7872,309 +7872,309 @@ static int zipfileEof(sqlite3_vtab_cursor *cur){ ** an English language error message may be left in virtual-table pTab. */ static int zipfileReadEOCD( - ZipfileTab *pTab, /* Return errors here */ - const u8 *aBlob, /* Pointer to in-memory file image */ - int nBlob, /* Size of aBlob[] in bytes */ - FILE *pFile, /* Read from this file if aBlob==0 */ - ZipfileEOCD *pEOCD /* Object to populate */ + ZipfileTab *pTab, /* Return errors here */ + const u8 *aBlob, /* Pointer to in-memory file image */ + int nBlob, /* Size of aBlob[] in bytes */ + FILE *pFile, /* Read from this file if aBlob==0 */ + ZipfileEOCD *pEOCD /* Object to populate */ ){ - u8 *aRead = pTab->aBuffer; /* Temporary buffer */ - int nRead; /* Bytes to read from file */ - int rc = SQLITE_OK; - - memset(pEOCD, 0, sizeof(ZipfileEOCD)); - if( aBlob==0 ){ - i64 iOff; /* Offset to read from */ - i64 szFile; /* Total size of file in bytes */ - fseek(pFile, 0, SEEK_END); - szFile = (i64)ftell(pFile); - if( szFile==0 ){ - return SQLITE_OK; - } - nRead = (int)(MIN(szFile, ZIPFILE_BUFFER_SIZE)); - iOff = szFile - nRead; - rc = zipfileReadData(pFile, aRead, nRead, iOff, &pTab->base.zErrMsg); - }else{ - nRead = (int)(MIN(nBlob, ZIPFILE_BUFFER_SIZE)); - aRead = (u8*)&aBlob[nBlob-nRead]; + u8 *aRead = pTab->aBuffer; /* Temporary buffer */ + int nRead; /* Bytes to read from file */ + int rc = SQLITE_OK; + + memset(pEOCD, 0, sizeof(ZipfileEOCD)); + if( aBlob==0 ){ + i64 iOff; /* Offset to read from */ + i64 szFile; /* Total size of file in bytes */ + fseek(pFile, 0, SEEK_END); + szFile = (i64)ftell(pFile); + if( szFile==0 ){ + return SQLITE_OK; + } + nRead = (int)(MIN(szFile, ZIPFILE_BUFFER_SIZE)); + iOff = szFile - nRead; + rc = zipfileReadData(pFile, aRead, nRead, iOff, &pTab->base.zErrMsg); + }else{ + nRead = (int)(MIN(nBlob, ZIPFILE_BUFFER_SIZE)); + aRead = (u8*)&aBlob[nBlob-nRead]; + } + + if( rc==SQLITE_OK ){ + int i; + + /* Scan backwards looking for the signature bytes */ + for(i=nRead-20; i>=0; i--){ + if( aRead[i]==0x50 && aRead[i+1]==0x4b + && aRead[i+2]==0x05 && aRead[i+3]==0x06 + ){ + break; + } + } + if( i<0 ){ + pTab->base.zErrMsg = sqlite3_mprintf( + "cannot find end of central directory record" + ); + return SQLITE_ERROR; } - if( rc==SQLITE_OK ){ - int i; + aRead += i+4; + pEOCD->iDisk = zipfileRead16(aRead); + pEOCD->iFirstDisk = zipfileRead16(aRead); + pEOCD->nEntry = zipfileRead16(aRead); + pEOCD->nEntryTotal = zipfileRead16(aRead); + pEOCD->nSize = zipfileRead32(aRead); + pEOCD->iOffset = zipfileRead32(aRead); + } - /* Scan backwards looking for the signature bytes */ - for(i=nRead-20; i>=0; i--){ - if( aRead[i]==0x50 && aRead[i+1]==0x4b - && aRead[i+2]==0x05 && aRead[i+3]==0x06 - ){ - break; - } - } - if( i<0 ){ - pTab->base.zErrMsg = sqlite3_mprintf( - "cannot find end of central directory record" - ); - return SQLITE_ERROR; - } - - aRead += i+4; - pEOCD->iDisk = zipfileRead16(aRead); - pEOCD->iFirstDisk = zipfileRead16(aRead); - pEOCD->nEntry = zipfileRead16(aRead); - pEOCD->nEntryTotal = zipfileRead16(aRead); - pEOCD->nSize = zipfileRead32(aRead); - pEOCD->iOffset = zipfileRead32(aRead); - } - - return rc; + return rc; } /* -** Add object pNew to the linked list that begins at ZipfileTab.pFirstEntry +** Add object pNew to the linked list that begins at ZipfileTab.pFirstEntry ** and ends with pLastEntry. If argument pBefore is NULL, then pNew is added ** to the end of the list. Otherwise, it is added to the list immediately ** before pBefore (which is guaranteed to be a part of said list). */ static void zipfileAddEntry( - ZipfileTab *pTab, - ZipfileEntry *pBefore, - ZipfileEntry *pNew + ZipfileTab *pTab, + ZipfileEntry *pBefore, + ZipfileEntry *pNew ){ - assert( (pTab->pFirstEntry==0)==(pTab->pLastEntry==0) ); - assert( pNew->pNext==0 ); - if( pBefore==0 ){ - if( pTab->pFirstEntry==0 ){ - pTab->pFirstEntry = pTab->pLastEntry = pNew; - }else{ - assert( pTab->pLastEntry->pNext==0 ); - pTab->pLastEntry->pNext = pNew; - pTab->pLastEntry = pNew; - } + assert( (pTab->pFirstEntry==0)==(pTab->pLastEntry==0) ); + assert( pNew->pNext==0 ); + if( pBefore==0 ){ + if( pTab->pFirstEntry==0 ){ + pTab->pFirstEntry = pTab->pLastEntry = pNew; }else{ - ZipfileEntry **pp; - for(pp=&pTab->pFirstEntry; *pp!=pBefore; pp=&((*pp)->pNext)); - pNew->pNext = pBefore; - *pp = pNew; + assert( pTab->pLastEntry->pNext==0 ); + pTab->pLastEntry->pNext = pNew; + pTab->pLastEntry = pNew; } + }else{ + ZipfileEntry **pp; + for(pp=&pTab->pFirstEntry; *pp!=pBefore; pp=&((*pp)->pNext)); + pNew->pNext = pBefore; + *pp = pNew; + } } static int zipfileLoadDirectory(ZipfileTab *pTab, const u8 *aBlob, int nBlob){ - ZipfileEOCD eocd; - int rc; - int i; - i64 iOff; + ZipfileEOCD eocd; + int rc; + int i; + i64 iOff; - rc = zipfileReadEOCD(pTab, aBlob, nBlob, pTab->pWriteFd, &eocd); - iOff = eocd.iOffset; - for(i=0; rc==SQLITE_OK && ipWriteFd, iOff, &pNew); + rc = zipfileReadEOCD(pTab, aBlob, nBlob, pTab->pWriteFd, &eocd); + iOff = eocd.iOffset; + for(i=0; rc==SQLITE_OK && ipWriteFd, iOff, &pNew); - if( rc==SQLITE_OK ){ - zipfileAddEntry(pTab, 0, pNew); - iOff += ZIPFILE_CDS_FIXED_SZ; - iOff += (int)pNew->cds.nExtra + pNew->cds.nFile + pNew->cds.nComment; - } + if( rc==SQLITE_OK ){ + zipfileAddEntry(pTab, 0, pNew); + iOff += ZIPFILE_CDS_FIXED_SZ; + iOff += (int)pNew->cds.nExtra + pNew->cds.nFile + pNew->cds.nComment; } - return rc; + } + return rc; } /* ** xFilter callback. */ static int zipfileFilter( - sqlite3_vtab_cursor *cur, - int idxNum, const char *idxStr, - int argc, sqlite3_value **argv + sqlite3_vtab_cursor *cur, + int idxNum, const char *idxStr, + int argc, sqlite3_value **argv ){ - ZipfileTab *pTab = (ZipfileTab*)cur->pVtab; - ZipfileCsr *pCsr = (ZipfileCsr*)cur; - const char *zFile = 0; /* Zip file to scan */ - int rc = SQLITE_OK; /* Return Code */ - int bInMemory = 0; /* True for an in-memory zipfile */ - - zipfileResetCursor(pCsr); - - if( pTab->zFile ){ - zFile = pTab->zFile; - }else if( idxNum==0 ){ - zipfileCursorErr(pCsr, "zipfile() function requires an argument"); - return SQLITE_ERROR; - }else if( sqlite3_value_type(argv[0])==SQLITE_BLOB ){ - const u8 *aBlob = (const u8*)sqlite3_value_blob(argv[0]); - int nBlob = sqlite3_value_bytes(argv[0]); - assert( pTab->pFirstEntry==0 ); - rc = zipfileLoadDirectory(pTab, aBlob, nBlob); - pCsr->pFreeEntry = pTab->pFirstEntry; - pTab->pFirstEntry = pTab->pLastEntry = 0; - if( rc!=SQLITE_OK ) return rc; - bInMemory = 1; - }else{ - zFile = (const char*)sqlite3_value_text(argv[0]); - } + ZipfileTab *pTab = (ZipfileTab*)cur->pVtab; + ZipfileCsr *pCsr = (ZipfileCsr*)cur; + const char *zFile = 0; /* Zip file to scan */ + int rc = SQLITE_OK; /* Return Code */ + int bInMemory = 0; /* True for an in-memory zipfile */ + + zipfileResetCursor(pCsr); + + if( pTab->zFile ){ + zFile = pTab->zFile; + }else if( idxNum==0 ){ + zipfileCursorErr(pCsr, "zipfile() function requires an argument"); + return SQLITE_ERROR; + }else if( sqlite3_value_type(argv[0])==SQLITE_BLOB ){ + const u8 *aBlob = (const u8*)sqlite3_value_blob(argv[0]); + int nBlob = sqlite3_value_bytes(argv[0]); + assert( pTab->pFirstEntry==0 ); + rc = zipfileLoadDirectory(pTab, aBlob, nBlob); + pCsr->pFreeEntry = pTab->pFirstEntry; + pTab->pFirstEntry = pTab->pLastEntry = 0; + if( rc!=SQLITE_OK ) return rc; + bInMemory = 1; + }else{ + zFile = (const char*)sqlite3_value_text(argv[0]); + } - if( 0==pTab->pWriteFd && 0==bInMemory ){ - pCsr->pFile = fopen(zFile, "rb"); - if( pCsr->pFile==0 ){ - zipfileCursorErr(pCsr, "cannot open file: %s", zFile); - rc = SQLITE_ERROR; + if( 0==pTab->pWriteFd && 0==bInMemory ){ + pCsr->pFile = fopen(zFile, "rb"); + if( pCsr->pFile==0 ){ + zipfileCursorErr(pCsr, "cannot open file: %s", zFile); + rc = SQLITE_ERROR; + }else{ + rc = zipfileReadEOCD(pTab, 0, 0, pCsr->pFile, &pCsr->eocd); + if( rc==SQLITE_OK ){ + if( pCsr->eocd.nEntry==0 ){ + pCsr->bEof = 1; }else{ - rc = zipfileReadEOCD(pTab, 0, 0, pCsr->pFile, &pCsr->eocd); - if( rc==SQLITE_OK ){ - if( pCsr->eocd.nEntry==0 ){ - pCsr->bEof = 1; - }else{ - pCsr->iNextOff = pCsr->eocd.iOffset; - rc = zipfileNext(cur); - } - } + pCsr->iNextOff = pCsr->eocd.iOffset; + rc = zipfileNext(cur); } - }else{ - pCsr->bNoop = 1; - pCsr->pCurrent = pCsr->pFreeEntry ? pCsr->pFreeEntry : pTab->pFirstEntry; - rc = zipfileNext(cur); + } } + }else{ + pCsr->bNoop = 1; + pCsr->pCurrent = pCsr->pFreeEntry ? pCsr->pFreeEntry : pTab->pFirstEntry; + rc = zipfileNext(cur); + } - return rc; + return rc; } /* ** xBestIndex callback. */ static int zipfileBestIndex( - sqlite3_vtab *tab, - sqlite3_index_info *pIdxInfo + sqlite3_vtab *tab, + sqlite3_index_info *pIdxInfo ){ - int i; - int idx = -1; - int unusable = 0; - - for(i=0; inConstraint; i++){ - const struct sqlite3_index_constraint *pCons = &pIdxInfo->aConstraint[i]; - if( pCons->iColumn!=ZIPFILE_F_COLUMN_IDX ) continue; - if( pCons->usable==0 ){ - unusable = 1; - }else if( pCons->op==SQLITE_INDEX_CONSTRAINT_EQ ){ - idx = i; - } - } - pIdxInfo->estimatedCost = 1000.0; - if( idx>=0 ){ - pIdxInfo->aConstraintUsage[idx].argvIndex = 1; - pIdxInfo->aConstraintUsage[idx].omit = 1; - pIdxInfo->idxNum = 1; - }else if( unusable ){ - return SQLITE_CONSTRAINT; - } - return SQLITE_OK; + int i; + int idx = -1; + int unusable = 0; + + for(i=0; inConstraint; i++){ + const struct sqlite3_index_constraint *pCons = &pIdxInfo->aConstraint[i]; + if( pCons->iColumn!=ZIPFILE_F_COLUMN_IDX ) continue; + if( pCons->usable==0 ){ + unusable = 1; + }else if( pCons->op==SQLITE_INDEX_CONSTRAINT_EQ ){ + idx = i; + } + } + pIdxInfo->estimatedCost = 1000.0; + if( idx>=0 ){ + pIdxInfo->aConstraintUsage[idx].argvIndex = 1; + pIdxInfo->aConstraintUsage[idx].omit = 1; + pIdxInfo->idxNum = 1; + }else if( unusable ){ + return SQLITE_CONSTRAINT; + } + return SQLITE_OK; } static ZipfileEntry *zipfileNewEntry(const char *zPath){ - ZipfileEntry *pNew; - pNew = sqlite3_malloc(sizeof(ZipfileEntry)); - if( pNew ){ - memset(pNew, 0, sizeof(ZipfileEntry)); - pNew->cds.zFile = sqlite3_mprintf("%s", zPath); - if( pNew->cds.zFile==0 ){ - sqlite3_free(pNew); - pNew = 0; - } + ZipfileEntry *pNew; + pNew = sqlite3_malloc(sizeof(ZipfileEntry)); + if( pNew ){ + memset(pNew, 0, sizeof(ZipfileEntry)); + pNew->cds.zFile = sqlite3_mprintf("%s", zPath); + if( pNew->cds.zFile==0 ){ + sqlite3_free(pNew); + pNew = 0; } - return pNew; + } + return pNew; } static int zipfileSerializeLFH(ZipfileEntry *pEntry, u8 *aBuf){ - ZipfileCDS *pCds = &pEntry->cds; - u8 *a = aBuf; - - pCds->nExtra = 9; - - /* Write the LFH itself */ - zipfileWrite32(a, ZIPFILE_SIGNATURE_LFH); - zipfileWrite16(a, pCds->iVersionExtract); - zipfileWrite16(a, pCds->flags); - zipfileWrite16(a, pCds->iCompression); - zipfileWrite16(a, pCds->mTime); - zipfileWrite16(a, pCds->mDate); - zipfileWrite32(a, pCds->crc32); - zipfileWrite32(a, pCds->szCompressed); - zipfileWrite32(a, pCds->szUncompressed); - zipfileWrite16(a, (u16)pCds->nFile); - zipfileWrite16(a, pCds->nExtra); - assert( a==&aBuf[ZIPFILE_LFH_FIXED_SZ] ); - - /* Add the file name */ - memcpy(a, pCds->zFile, (int)pCds->nFile); - a += (int)pCds->nFile; - - /* The "extra" data */ - zipfileWrite16(a, ZIPFILE_EXTRA_TIMESTAMP); - zipfileWrite16(a, 5); - *a++ = 0x01; - zipfileWrite32(a, pEntry->mUnixTime); - - return a-aBuf; + ZipfileCDS *pCds = &pEntry->cds; + u8 *a = aBuf; + + pCds->nExtra = 9; + + /* Write the LFH itself */ + zipfileWrite32(a, ZIPFILE_SIGNATURE_LFH); + zipfileWrite16(a, pCds->iVersionExtract); + zipfileWrite16(a, pCds->flags); + zipfileWrite16(a, pCds->iCompression); + zipfileWrite16(a, pCds->mTime); + zipfileWrite16(a, pCds->mDate); + zipfileWrite32(a, pCds->crc32); + zipfileWrite32(a, pCds->szCompressed); + zipfileWrite32(a, pCds->szUncompressed); + zipfileWrite16(a, (u16)pCds->nFile); + zipfileWrite16(a, pCds->nExtra); + assert( a==&aBuf[ZIPFILE_LFH_FIXED_SZ] ); + + /* Add the file name */ + memcpy(a, pCds->zFile, (int)pCds->nFile); + a += (int)pCds->nFile; + + /* The "extra" data */ + zipfileWrite16(a, ZIPFILE_EXTRA_TIMESTAMP); + zipfileWrite16(a, 5); + *a++ = 0x01; + zipfileWrite32(a, pEntry->mUnixTime); + + return a-aBuf; } static int zipfileAppendEntry( - ZipfileTab *pTab, - ZipfileEntry *pEntry, - const u8 *pData, - int nData + ZipfileTab *pTab, + ZipfileEntry *pEntry, + const u8 *pData, + int nData ){ - u8 *aBuf = pTab->aBuffer; - int nBuf; - int rc; + u8 *aBuf = pTab->aBuffer; + int nBuf; + int rc; - nBuf = zipfileSerializeLFH(pEntry, aBuf); - rc = zipfileAppendData(pTab, aBuf, nBuf); - if( rc==SQLITE_OK ){ - pEntry->iDataOff = pTab->szCurrent; - rc = zipfileAppendData(pTab, pData, nData); - } + nBuf = zipfileSerializeLFH(pEntry, aBuf); + rc = zipfileAppendData(pTab, aBuf, nBuf); + if( rc==SQLITE_OK ){ + pEntry->iDataOff = pTab->szCurrent; + rc = zipfileAppendData(pTab, pData, nData); + } - return rc; + return rc; } static int zipfileGetMode( - sqlite3_value *pVal, - int bIsDir, /* If true, default to directory */ - u32 *pMode, /* OUT: Mode value */ - char **pzErr /* OUT: Error message */ + sqlite3_value *pVal, + int bIsDir, /* If true, default to directory */ + u32 *pMode, /* OUT: Mode value */ + char **pzErr /* OUT: Error message */ ){ - const char *z = (const char*)sqlite3_value_text(pVal); - u32 mode = 0; - if( z==0 ){ - mode = (bIsDir ? (S_IFDIR + 0755) : (S_IFREG + 0644)); - }else if( z[0]>='0' && z[0]<='9' ){ - mode = (unsigned int)sqlite3_value_int(pVal); - }else{ - const char zTemplate[11] = "-rwxrwxrwx"; - int i; - if( strlen(z)!=10 ) goto parse_error; - switch( z[0] ){ - case '-': mode |= S_IFREG; break; - case 'd': mode |= S_IFDIR; break; - case 'l': mode |= S_IFLNK; break; - default: goto parse_error; - } - for(i=1; i<10; i++){ - if( z[i]==zTemplate[i] ) mode |= 1 << (9-i); - else if( z[i]!='-' ) goto parse_error; - } - } - if( ((mode & S_IFDIR)==0)==bIsDir ){ - /* The "mode" attribute is a directory, but data has been specified. + const char *z = (const char*)sqlite3_value_text(pVal); + u32 mode = 0; + if( z==0 ){ + mode = (bIsDir ? (S_IFDIR + 0755) : (S_IFREG + 0644)); + }else if( z[0]>='0' && z[0]<='9' ){ + mode = (unsigned int)sqlite3_value_int(pVal); + }else{ + const char zTemplate[11] = "-rwxrwxrwx"; + int i; + if( strlen(z)!=10 ) goto parse_error; + switch( z[0] ){ + case '-': mode |= S_IFREG; break; + case 'd': mode |= S_IFDIR; break; + case 'l': mode |= S_IFLNK; break; + default: goto parse_error; + } + for(i=1; i<10; i++){ + if( z[i]==zTemplate[i] ) mode |= 1 << (9-i); + else if( z[i]!='-' ) goto parse_error; + } + } + if( ((mode & S_IFDIR)==0)==bIsDir ){ + /* The "mode" attribute is a directory, but data has been specified. ** Or vice-versa - no data but "mode" is a file or symlink. */ - *pzErr = sqlite3_mprintf("zipfile: mode does not match data"); - return SQLITE_CONSTRAINT; - } - *pMode = mode; - return SQLITE_OK; + *pzErr = sqlite3_mprintf("zipfile: mode does not match data"); + return SQLITE_CONSTRAINT; + } + *pMode = mode; + return SQLITE_OK; -parse_error: - *pzErr = sqlite3_mprintf("zipfile: parse error in mode: %s", z); - return SQLITE_ERROR; + parse_error: + *pzErr = sqlite3_mprintf("zipfile: parse error in mode: %s", z); + return SQLITE_ERROR; } /* @@ -8182,44 +8182,44 @@ parse_error: ** nB is the value of strlen(zB). This function returns 0 if the strings are ** identical, ignoring any trailing '/' character in either path. */ static int zipfileComparePath(const char *zA, const char *zB, int nB){ - int nA = (int)strlen(zA); - if( nA>0 && zA[nA-1]=='/' ) nA--; - if( nB>0 && zB[nB-1]=='/' ) nB--; - if( nA==nB && memcmp(zA, zB, nA)==0 ) return 0; - return 1; + int nA = (int)strlen(zA); + if( nA>0 && zA[nA-1]=='/' ) nA--; + if( nB>0 && zB[nB-1]=='/' ) nB--; + if( nA==nB && memcmp(zA, zB, nA)==0 ) return 0; + return 1; } static int zipfileBegin(sqlite3_vtab *pVtab){ - ZipfileTab *pTab = (ZipfileTab*)pVtab; - int rc = SQLITE_OK; + ZipfileTab *pTab = (ZipfileTab*)pVtab; + int rc = SQLITE_OK; - assert( pTab->pWriteFd==0 ); - if( pTab->zFile==0 || pTab->zFile[0]==0 ){ - pTab->base.zErrMsg = sqlite3_mprintf("zipfile: missing filename"); - return SQLITE_ERROR; - } + assert( pTab->pWriteFd==0 ); + if( pTab->zFile==0 || pTab->zFile[0]==0 ){ + pTab->base.zErrMsg = sqlite3_mprintf("zipfile: missing filename"); + return SQLITE_ERROR; + } - /* Open a write fd on the file. Also load the entire central directory - ** structure into memory. During the transaction any new file data is + /* Open a write fd on the file. Also load the entire central directory + ** structure into memory. During the transaction any new file data is ** appended to the archive file, but the central directory is accumulated ** in main-memory until the transaction is committed. */ - pTab->pWriteFd = fopen(pTab->zFile, "ab+"); - if( pTab->pWriteFd==0 ){ - pTab->base.zErrMsg = sqlite3_mprintf( - "zipfile: failed to open file %s for writing", pTab->zFile + pTab->pWriteFd = fopen(pTab->zFile, "ab+"); + if( pTab->pWriteFd==0 ){ + pTab->base.zErrMsg = sqlite3_mprintf( + "zipfile: failed to open file %s for writing", pTab->zFile ); - rc = SQLITE_ERROR; - }else{ - fseek(pTab->pWriteFd, 0, SEEK_END); - pTab->szCurrent = pTab->szOrig = (i64)ftell(pTab->pWriteFd); - rc = zipfileLoadDirectory(pTab, 0, 0); - } + rc = SQLITE_ERROR; + }else{ + fseek(pTab->pWriteFd, 0, SEEK_END); + pTab->szCurrent = pTab->szOrig = (i64)ftell(pTab->pWriteFd); + rc = zipfileLoadDirectory(pTab, 0, 0); + } - if( rc!=SQLITE_OK ){ - zipfileCleanupTransaction(pTab); - } + if( rc!=SQLITE_OK ){ + zipfileCleanupTransaction(pTab); + } - return rc; + return rc; } /* @@ -8227,19 +8227,19 @@ static int zipfileBegin(sqlite3_vtab *pVtab){ ** time(2)). */ static u32 zipfileTime(void){ - sqlite3_vfs *pVfs = sqlite3_vfs_find(0); - u32 ret; - if( pVfs==0 ) return 0; - if( pVfs->iVersion>=2 && pVfs->xCurrentTimeInt64 ){ - i64 ms; - pVfs->xCurrentTimeInt64(pVfs, &ms); - ret = (u32)((ms/1000) - ((i64)24405875 * 8640)); - }else{ - double day; - pVfs->xCurrentTime(pVfs, &day); - ret = (u32)((day - 2440587.5) * 86400); - } - return ret; + sqlite3_vfs *pVfs = sqlite3_vfs_find(0); + u32 ret; + if( pVfs==0 ) return 0; + if( pVfs->iVersion>=2 && pVfs->xCurrentTimeInt64 ){ + i64 ms; + pVfs->xCurrentTimeInt64(pVfs, &ms); + ret = (u32)((ms/1000) - ((i64)24405875 * 8640)); + }else{ + double day; + pVfs->xCurrentTime(pVfs, &day); + ret = (u32)((day - 2440587.5) * 86400); + } + return ret; } /* @@ -8250,10 +8250,10 @@ static u32 zipfileTime(void){ ** cast to a 32-bit unsigned integer. */ static u32 zipfileGetTime(sqlite3_value *pVal){ - if( pVal==0 || sqlite3_value_type(pVal)==SQLITE_NULL ){ - return zipfileTime(); - } - return (u32)sqlite3_value_int64(pVal); + if( pVal==0 || sqlite3_value_type(pVal)==SQLITE_NULL ){ + return zipfileTime(); + } + return (u32)sqlite3_value_int64(pVal); } /* @@ -8261,226 +8261,226 @@ static u32 zipfileGetTime(sqlite3_value *pVal){ ** linked list. Remove it from the list and free the object. */ static void zipfileRemoveEntryFromList(ZipfileTab *pTab, ZipfileEntry *pOld){ - if( pOld ){ - ZipfileEntry **pp; - for(pp=&pTab->pFirstEntry; (*pp)!=pOld; pp=&((*pp)->pNext)); - *pp = (*pp)->pNext; - zipfileEntryFree(pOld); - } + if( pOld ){ + ZipfileEntry **pp; + for(pp=&pTab->pFirstEntry; (*pp)!=pOld; pp=&((*pp)->pNext)); + *pp = (*pp)->pNext; + zipfileEntryFree(pOld); + } } /* ** xUpdate method. */ static int zipfileUpdate( - sqlite3_vtab *pVtab, - int nVal, - sqlite3_value **apVal, - sqlite_int64 *pRowid + sqlite3_vtab *pVtab, + int nVal, + sqlite3_value **apVal, + sqlite_int64 *pRowid ){ - ZipfileTab *pTab = (ZipfileTab*)pVtab; - int rc = SQLITE_OK; /* Return Code */ - ZipfileEntry *pNew = 0; /* New in-memory CDS entry */ - - u32 mode = 0; /* Mode for new entry */ - u32 mTime = 0; /* Modification time for new entry */ - i64 sz = 0; /* Uncompressed size */ - const char *zPath = 0; /* Path for new entry */ - int nPath = 0; /* strlen(zPath) */ - const u8 *pData = 0; /* Pointer to buffer containing content */ - int nData = 0; /* Size of pData buffer in bytes */ - int iMethod = 0; /* Compression method for new entry */ - u8 *pFree = 0; /* Free this */ - char *zFree = 0; /* Also free this */ - ZipfileEntry *pOld = 0; - ZipfileEntry *pOld2 = 0; - int bUpdate = 0; /* True for an update that modifies "name" */ - int bIsDir = 0; - u32 iCrc32 = 0; - - if( pTab->pWriteFd==0 ){ - rc = zipfileBegin(pVtab); - if( rc!=SQLITE_OK ) return rc; - } + ZipfileTab *pTab = (ZipfileTab*)pVtab; + int rc = SQLITE_OK; /* Return Code */ + ZipfileEntry *pNew = 0; /* New in-memory CDS entry */ + + u32 mode = 0; /* Mode for new entry */ + u32 mTime = 0; /* Modification time for new entry */ + i64 sz = 0; /* Uncompressed size */ + const char *zPath = 0; /* Path for new entry */ + int nPath = 0; /* strlen(zPath) */ + const u8 *pData = 0; /* Pointer to buffer containing content */ + int nData = 0; /* Size of pData buffer in bytes */ + int iMethod = 0; /* Compression method for new entry */ + u8 *pFree = 0; /* Free this */ + char *zFree = 0; /* Also free this */ + ZipfileEntry *pOld = 0; + ZipfileEntry *pOld2 = 0; + int bUpdate = 0; /* True for an update that modifies "name" */ + int bIsDir = 0; + u32 iCrc32 = 0; + + if( pTab->pWriteFd==0 ){ + rc = zipfileBegin(pVtab); + if( rc!=SQLITE_OK ) return rc; + } - /* If this is a DELETE or UPDATE, find the archive entry to delete. */ - if( sqlite3_value_type(apVal[0])!=SQLITE_NULL ){ - const char *zDelete = (const char*)sqlite3_value_text(apVal[0]); - int nDelete = (int)strlen(zDelete); - if( nVal>1 ){ - const char *zUpdate = (const char*)sqlite3_value_text(apVal[1]); - if( zUpdate && zipfileComparePath(zUpdate, zDelete, nDelete)!=0 ){ - bUpdate = 1; - } - } - for(pOld=pTab->pFirstEntry; 1; pOld=pOld->pNext){ - if( zipfileComparePath(pOld->cds.zFile, zDelete, nDelete)==0 ){ - break; - } - assert( pOld->pNext ); - } + /* If this is a DELETE or UPDATE, find the archive entry to delete. */ + if( sqlite3_value_type(apVal[0])!=SQLITE_NULL ){ + const char *zDelete = (const char*)sqlite3_value_text(apVal[0]); + int nDelete = (int)strlen(zDelete); + if( nVal>1 ){ + const char *zUpdate = (const char*)sqlite3_value_text(apVal[1]); + if( zUpdate && zipfileComparePath(zUpdate, zDelete, nDelete)!=0 ){ + bUpdate = 1; + } + } + for(pOld=pTab->pFirstEntry; 1; pOld=pOld->pNext){ + if( zipfileComparePath(pOld->cds.zFile, zDelete, nDelete)==0 ){ + break; + } + assert( pOld->pNext ); } + } - if( nVal>1 ){ - /* Check that "sz" and "rawdata" are both NULL: */ - if( sqlite3_value_type(apVal[5])!=SQLITE_NULL ){ - zipfileTableErr(pTab, "sz must be NULL"); - rc = SQLITE_CONSTRAINT; - } - if( sqlite3_value_type(apVal[6])!=SQLITE_NULL ){ - zipfileTableErr(pTab, "rawdata must be NULL"); - rc = SQLITE_CONSTRAINT; - } + if( nVal>1 ){ + /* Check that "sz" and "rawdata" are both NULL: */ + if( sqlite3_value_type(apVal[5])!=SQLITE_NULL ){ + zipfileTableErr(pTab, "sz must be NULL"); + rc = SQLITE_CONSTRAINT; + } + if( sqlite3_value_type(apVal[6])!=SQLITE_NULL ){ + zipfileTableErr(pTab, "rawdata must be NULL"); + rc = SQLITE_CONSTRAINT; + } - if( rc==SQLITE_OK ){ - if( sqlite3_value_type(apVal[7])==SQLITE_NULL ){ - /* data=NULL. A directory */ - bIsDir = 1; - }else{ - /* Value specified for "data", and possibly "method". This must be + if( rc==SQLITE_OK ){ + if( sqlite3_value_type(apVal[7])==SQLITE_NULL ){ + /* data=NULL. A directory */ + bIsDir = 1; + }else{ + /* Value specified for "data", and possibly "method". This must be ** a regular file or a symlink. */ - const u8 *aIn = sqlite3_value_blob(apVal[7]); - int nIn = sqlite3_value_bytes(apVal[7]); - int bAuto = sqlite3_value_type(apVal[8])==SQLITE_NULL; - - iMethod = sqlite3_value_int(apVal[8]); - sz = nIn; - pData = aIn; - nData = nIn; - if( iMethod!=0 && iMethod!=8 ){ - zipfileTableErr(pTab, "unknown compression method: %d", iMethod); - rc = SQLITE_CONSTRAINT; - }else{ - if( bAuto || iMethod ){ - int nCmp; - rc = zipfileDeflate(aIn, nIn, &pFree, &nCmp, &pTab->base.zErrMsg); - if( rc==SQLITE_OK ){ - if( iMethod || nCmpbase.zErrMsg); + if( rc==SQLITE_OK ){ + if( iMethod || nCmpbase.zErrMsg); - } + if( rc==SQLITE_OK ){ + rc = zipfileGetMode(apVal[3], bIsDir, &mode, &pTab->base.zErrMsg); + } - if( rc==SQLITE_OK ){ - zPath = (const char*)sqlite3_value_text(apVal[2]); - if( zPath==0 ) zPath = ""; - nPath = (int)strlen(zPath); - mTime = zipfileGetTime(apVal[4]); - } + if( rc==SQLITE_OK ){ + zPath = (const char*)sqlite3_value_text(apVal[2]); + if( zPath==0 ) zPath = ""; + nPath = (int)strlen(zPath); + mTime = zipfileGetTime(apVal[4]); + } - if( rc==SQLITE_OK && bIsDir ){ - /* For a directory, check that the last character in the path is a + if( rc==SQLITE_OK && bIsDir ){ + /* For a directory, check that the last character in the path is a ** '/'. This appears to be required for compatibility with info-zip ** (the unzip command on unix). It does not create directories ** otherwise. */ - if( nPath<=0 || zPath[nPath-1]!='/' ){ - zFree = sqlite3_mprintf("%s/", zPath); - zPath = (const char*)zFree; - if( zFree==0 ){ - rc = SQLITE_NOMEM; - nPath = 0; - }else{ - nPath = (int)strlen(zPath); - } - } + if( nPath<=0 || zPath[nPath-1]!='/' ){ + zFree = sqlite3_mprintf("%s/", zPath); + zPath = (const char*)zFree; + if( zFree==0 ){ + rc = SQLITE_NOMEM; + nPath = 0; + }else{ + nPath = (int)strlen(zPath); } + } + } - /* Check that we're not inserting a duplicate entry -OR- updating an + /* Check that we're not inserting a duplicate entry -OR- updating an ** entry with a path, thereby making it into a duplicate. */ - if( (pOld==0 || bUpdate) && rc==SQLITE_OK ){ - ZipfileEntry *p; - for(p=pTab->pFirstEntry; p; p=p->pNext){ - if( zipfileComparePath(p->cds.zFile, zPath, nPath)==0 ){ - switch( sqlite3_vtab_on_conflict(pTab->db) ){ - case SQLITE_IGNORE: { - goto zipfile_update_done; - } - case SQLITE_REPLACE: { - pOld2 = p; - break; - } - default: { - zipfileTableErr(pTab, "duplicate name: \"%s\"", zPath); - rc = SQLITE_CONSTRAINT; - break; - } - } - break; - } + if( (pOld==0 || bUpdate) && rc==SQLITE_OK ){ + ZipfileEntry *p; + for(p=pTab->pFirstEntry; p; p=p->pNext){ + if( zipfileComparePath(p->cds.zFile, zPath, nPath)==0 ){ + switch( sqlite3_vtab_on_conflict(pTab->db) ){ + case SQLITE_IGNORE: { + goto zipfile_update_done; + } + case SQLITE_REPLACE: { + pOld2 = p; + break; } - } - - if( rc==SQLITE_OK ){ - /* Create the new CDS record. */ - pNew = zipfileNewEntry(zPath); - if( pNew==0 ){ - rc = SQLITE_NOMEM; - }else{ - pNew->cds.iVersionMadeBy = ZIPFILE_NEWENTRY_MADEBY; - pNew->cds.iVersionExtract = ZIPFILE_NEWENTRY_REQUIRED; - pNew->cds.flags = ZIPFILE_NEWENTRY_FLAGS; - pNew->cds.iCompression = (u16)iMethod; - zipfileMtimeToDos(&pNew->cds, mTime); - pNew->cds.crc32 = iCrc32; - pNew->cds.szCompressed = nData; - pNew->cds.szUncompressed = (u32)sz; - pNew->cds.iExternalAttr = (mode<<16); - pNew->cds.iOffset = (u32)pTab->szCurrent; - pNew->cds.nFile = (u16)nPath; - pNew->mUnixTime = (u32)mTime; - rc = zipfileAppendEntry(pTab, pNew, pData, nData); - zipfileAddEntry(pTab, pOld, pNew); + default: { + zipfileTableErr(pTab, "duplicate name: \"%s\"", zPath); + rc = SQLITE_CONSTRAINT; + break; } + } + break; } + } } - if( rc==SQLITE_OK && (pOld || pOld2) ){ - ZipfileCsr *pCsr; - for(pCsr=pTab->pCsrList; pCsr; pCsr=pCsr->pCsrNext){ - if( pCsr->pCurrent && (pCsr->pCurrent==pOld || pCsr->pCurrent==pOld2) ){ - pCsr->pCurrent = pCsr->pCurrent->pNext; - pCsr->bNoop = 1; - } - } - - zipfileRemoveEntryFromList(pTab, pOld); - zipfileRemoveEntryFromList(pTab, pOld2); + if( rc==SQLITE_OK ){ + /* Create the new CDS record. */ + pNew = zipfileNewEntry(zPath); + if( pNew==0 ){ + rc = SQLITE_NOMEM; + }else{ + pNew->cds.iVersionMadeBy = ZIPFILE_NEWENTRY_MADEBY; + pNew->cds.iVersionExtract = ZIPFILE_NEWENTRY_REQUIRED; + pNew->cds.flags = ZIPFILE_NEWENTRY_FLAGS; + pNew->cds.iCompression = (u16)iMethod; + zipfileMtimeToDos(&pNew->cds, mTime); + pNew->cds.crc32 = iCrc32; + pNew->cds.szCompressed = nData; + pNew->cds.szUncompressed = (u32)sz; + pNew->cds.iExternalAttr = (mode<<16); + pNew->cds.iOffset = (u32)pTab->szCurrent; + pNew->cds.nFile = (u16)nPath; + pNew->mUnixTime = (u32)mTime; + rc = zipfileAppendEntry(pTab, pNew, pData, nData); + zipfileAddEntry(pTab, pOld, pNew); + } + } + } + + if( rc==SQLITE_OK && (pOld || pOld2) ){ + ZipfileCsr *pCsr; + for(pCsr=pTab->pCsrList; pCsr; pCsr=pCsr->pCsrNext){ + if( pCsr->pCurrent && (pCsr->pCurrent==pOld || pCsr->pCurrent==pOld2) ){ + pCsr->pCurrent = pCsr->pCurrent->pNext; + pCsr->bNoop = 1; + } } + zipfileRemoveEntryFromList(pTab, pOld); + zipfileRemoveEntryFromList(pTab, pOld2); + } + zipfile_update_done: - sqlite3_free(pFree); - sqlite3_free(zFree); - return rc; + sqlite3_free(pFree); + sqlite3_free(zFree); + return rc; } static int zipfileSerializeEOCD(ZipfileEOCD *p, u8 *aBuf){ - u8 *a = aBuf; - zipfileWrite32(a, ZIPFILE_SIGNATURE_EOCD); - zipfileWrite16(a, p->iDisk); - zipfileWrite16(a, p->iFirstDisk); - zipfileWrite16(a, p->nEntry); - zipfileWrite16(a, p->nEntryTotal); - zipfileWrite32(a, p->nSize); - zipfileWrite32(a, p->iOffset); - zipfileWrite16(a, 0); /* Size of trailing comment in bytes*/ + u8 *a = aBuf; + zipfileWrite32(a, ZIPFILE_SIGNATURE_EOCD); + zipfileWrite16(a, p->iDisk); + zipfileWrite16(a, p->iFirstDisk); + zipfileWrite16(a, p->nEntry); + zipfileWrite16(a, p->nEntryTotal); + zipfileWrite32(a, p->nSize); + zipfileWrite32(a, p->iOffset); + zipfileWrite16(a, 0); /* Size of trailing comment in bytes*/ - return a-aBuf; + return a-aBuf; } static int zipfileAppendEOCD(ZipfileTab *pTab, ZipfileEOCD *p){ - int nBuf = zipfileSerializeEOCD(p, pTab->aBuffer); - assert( nBuf==ZIPFILE_EOCD_FIXED_SZ ); - return zipfileAppendData(pTab, pTab->aBuffer, nBuf); + int nBuf = zipfileSerializeEOCD(p, pTab->aBuffer); + assert( nBuf==ZIPFILE_EOCD_FIXED_SZ ); + return zipfileAppendData(pTab, pTab->aBuffer, nBuf); } /* @@ -8488,185 +8488,185 @@ static int zipfileAppendEOCD(ZipfileTab *pTab, ZipfileEOCD *p){ ** of bytes written. */ static int zipfileSerializeCDS(ZipfileEntry *pEntry, u8 *aBuf){ - u8 *a = aBuf; - ZipfileCDS *pCDS = &pEntry->cds; - - if( pEntry->aExtra==0 ){ - pCDS->nExtra = 9; - } - - zipfileWrite32(a, ZIPFILE_SIGNATURE_CDS); - zipfileWrite16(a, pCDS->iVersionMadeBy); - zipfileWrite16(a, pCDS->iVersionExtract); - zipfileWrite16(a, pCDS->flags); - zipfileWrite16(a, pCDS->iCompression); - zipfileWrite16(a, pCDS->mTime); - zipfileWrite16(a, pCDS->mDate); - zipfileWrite32(a, pCDS->crc32); - zipfileWrite32(a, pCDS->szCompressed); - zipfileWrite32(a, pCDS->szUncompressed); - assert( a==&aBuf[ZIPFILE_CDS_NFILE_OFF] ); - zipfileWrite16(a, pCDS->nFile); - zipfileWrite16(a, pCDS->nExtra); - zipfileWrite16(a, pCDS->nComment); - zipfileWrite16(a, pCDS->iDiskStart); - zipfileWrite16(a, pCDS->iInternalAttr); - zipfileWrite32(a, pCDS->iExternalAttr); - zipfileWrite32(a, pCDS->iOffset); - - memcpy(a, pCDS->zFile, pCDS->nFile); - a += pCDS->nFile; - - if( pEntry->aExtra ){ - int n = (int)pCDS->nExtra + (int)pCDS->nComment; - memcpy(a, pEntry->aExtra, n); - a += n; - }else{ - assert( pCDS->nExtra==9 ); - zipfileWrite16(a, ZIPFILE_EXTRA_TIMESTAMP); - zipfileWrite16(a, 5); - *a++ = 0x01; - zipfileWrite32(a, pEntry->mUnixTime); - } + u8 *a = aBuf; + ZipfileCDS *pCDS = &pEntry->cds; + + if( pEntry->aExtra==0 ){ + pCDS->nExtra = 9; + } + + zipfileWrite32(a, ZIPFILE_SIGNATURE_CDS); + zipfileWrite16(a, pCDS->iVersionMadeBy); + zipfileWrite16(a, pCDS->iVersionExtract); + zipfileWrite16(a, pCDS->flags); + zipfileWrite16(a, pCDS->iCompression); + zipfileWrite16(a, pCDS->mTime); + zipfileWrite16(a, pCDS->mDate); + zipfileWrite32(a, pCDS->crc32); + zipfileWrite32(a, pCDS->szCompressed); + zipfileWrite32(a, pCDS->szUncompressed); + assert( a==&aBuf[ZIPFILE_CDS_NFILE_OFF] ); + zipfileWrite16(a, pCDS->nFile); + zipfileWrite16(a, pCDS->nExtra); + zipfileWrite16(a, pCDS->nComment); + zipfileWrite16(a, pCDS->iDiskStart); + zipfileWrite16(a, pCDS->iInternalAttr); + zipfileWrite32(a, pCDS->iExternalAttr); + zipfileWrite32(a, pCDS->iOffset); + + memcpy(a, pCDS->zFile, pCDS->nFile); + a += pCDS->nFile; + + if( pEntry->aExtra ){ + int n = (int)pCDS->nExtra + (int)pCDS->nComment; + memcpy(a, pEntry->aExtra, n); + a += n; + }else{ + assert( pCDS->nExtra==9 ); + zipfileWrite16(a, ZIPFILE_EXTRA_TIMESTAMP); + zipfileWrite16(a, 5); + *a++ = 0x01; + zipfileWrite32(a, pEntry->mUnixTime); + } - return a-aBuf; + return a-aBuf; } static int zipfileCommit(sqlite3_vtab *pVtab){ - ZipfileTab *pTab = (ZipfileTab*)pVtab; - int rc = SQLITE_OK; - if( pTab->pWriteFd ){ - i64 iOffset = pTab->szCurrent; - ZipfileEntry *p; - ZipfileEOCD eocd; - int nEntry = 0; - - /* Write out all entries */ - for(p=pTab->pFirstEntry; rc==SQLITE_OK && p; p=p->pNext){ - int n = zipfileSerializeCDS(p, pTab->aBuffer); - rc = zipfileAppendData(pTab, pTab->aBuffer, n); - nEntry++; - } - - /* Write out the EOCD record */ - eocd.iDisk = 0; - eocd.iFirstDisk = 0; - eocd.nEntry = (u16)nEntry; - eocd.nEntryTotal = (u16)nEntry; - eocd.nSize = (u32)(pTab->szCurrent - iOffset); - eocd.iOffset = (u32)iOffset; - rc = zipfileAppendEOCD(pTab, &eocd); + ZipfileTab *pTab = (ZipfileTab*)pVtab; + int rc = SQLITE_OK; + if( pTab->pWriteFd ){ + i64 iOffset = pTab->szCurrent; + ZipfileEntry *p; + ZipfileEOCD eocd; + int nEntry = 0; - zipfileCleanupTransaction(pTab); + /* Write out all entries */ + for(p=pTab->pFirstEntry; rc==SQLITE_OK && p; p=p->pNext){ + int n = zipfileSerializeCDS(p, pTab->aBuffer); + rc = zipfileAppendData(pTab, pTab->aBuffer, n); + nEntry++; } - return rc; + + /* Write out the EOCD record */ + eocd.iDisk = 0; + eocd.iFirstDisk = 0; + eocd.nEntry = (u16)nEntry; + eocd.nEntryTotal = (u16)nEntry; + eocd.nSize = (u32)(pTab->szCurrent - iOffset); + eocd.iOffset = (u32)iOffset; + rc = zipfileAppendEOCD(pTab, &eocd); + + zipfileCleanupTransaction(pTab); + } + return rc; } static int zipfileRollback(sqlite3_vtab *pVtab){ - return zipfileCommit(pVtab); + return zipfileCommit(pVtab); } static ZipfileCsr *zipfileFindCursor(ZipfileTab *pTab, i64 iId){ - ZipfileCsr *pCsr; - for(pCsr=pTab->pCsrList; pCsr; pCsr=pCsr->pCsrNext){ - if( iId==pCsr->iId ) break; - } - return pCsr; + ZipfileCsr *pCsr; + for(pCsr=pTab->pCsrList; pCsr; pCsr=pCsr->pCsrNext){ + if( iId==pCsr->iId ) break; + } + return pCsr; } static void zipfileFunctionCds( - sqlite3_context *context, - int argc, - sqlite3_value **argv + sqlite3_context *context, + int argc, + sqlite3_value **argv ){ - ZipfileCsr *pCsr; - ZipfileTab *pTab = (ZipfileTab*)sqlite3_user_data(context); - assert( argc>0 ); - - pCsr = zipfileFindCursor(pTab, sqlite3_value_int64(argv[0])); - if( pCsr ){ - ZipfileCDS *p = &pCsr->pCurrent->cds; - char *zRes = sqlite3_mprintf("{" - "\"version-made-by\" : %u, " - "\"version-to-extract\" : %u, " - "\"flags\" : %u, " - "\"compression\" : %u, " - "\"time\" : %u, " - "\"date\" : %u, " - "\"crc32\" : %u, " - "\"compressed-size\" : %u, " - "\"uncompressed-size\" : %u, " - "\"file-name-length\" : %u, " - "\"extra-field-length\" : %u, " - "\"file-comment-length\" : %u, " - "\"disk-number-start\" : %u, " - "\"internal-attr\" : %u, " - "\"external-attr\" : %u, " - "\"offset\" : %u }", - (u32)p->iVersionMadeBy, (u32)p->iVersionExtract, - (u32)p->flags, (u32)p->iCompression, - (u32)p->mTime, (u32)p->mDate, - (u32)p->crc32, (u32)p->szCompressed, - (u32)p->szUncompressed, (u32)p->nFile, - (u32)p->nExtra, (u32)p->nComment, - (u32)p->iDiskStart, (u32)p->iInternalAttr, - (u32)p->iExternalAttr, (u32)p->iOffset - ); + ZipfileCsr *pCsr; + ZipfileTab *pTab = (ZipfileTab*)sqlite3_user_data(context); + assert( argc>0 ); + + pCsr = zipfileFindCursor(pTab, sqlite3_value_int64(argv[0])); + if( pCsr ){ + ZipfileCDS *p = &pCsr->pCurrent->cds; + char *zRes = sqlite3_mprintf("{" + "\"version-made-by\" : %u, " + "\"version-to-extract\" : %u, " + "\"flags\" : %u, " + "\"compression\" : %u, " + "\"time\" : %u, " + "\"date\" : %u, " + "\"crc32\" : %u, " + "\"compressed-size\" : %u, " + "\"uncompressed-size\" : %u, " + "\"file-name-length\" : %u, " + "\"extra-field-length\" : %u, " + "\"file-comment-length\" : %u, " + "\"disk-number-start\" : %u, " + "\"internal-attr\" : %u, " + "\"external-attr\" : %u, " + "\"offset\" : %u }", + (u32)p->iVersionMadeBy, (u32)p->iVersionExtract, + (u32)p->flags, (u32)p->iCompression, + (u32)p->mTime, (u32)p->mDate, + (u32)p->crc32, (u32)p->szCompressed, + (u32)p->szUncompressed, (u32)p->nFile, + (u32)p->nExtra, (u32)p->nComment, + (u32)p->iDiskStart, (u32)p->iInternalAttr, + (u32)p->iExternalAttr, (u32)p->iOffset + ); - if( zRes==0 ){ - sqlite3_result_error_nomem(context); - }else{ - sqlite3_result_text(context, zRes, -1, SQLITE_TRANSIENT); - sqlite3_free(zRes); - } + if( zRes==0 ){ + sqlite3_result_error_nomem(context); + }else{ + sqlite3_result_text(context, zRes, -1, SQLITE_TRANSIENT); + sqlite3_free(zRes); } + } } /* ** xFindFunction method. */ static int zipfileFindFunction( - sqlite3_vtab *pVtab, /* Virtual table handle */ - int nArg, /* Number of SQL function arguments */ - const char *zName, /* Name of SQL function */ - void (**pxFunc)(sqlite3_context*,int,sqlite3_value**), /* OUT: Result */ - void **ppArg /* OUT: User data for *pxFunc */ + sqlite3_vtab *pVtab, /* Virtual table handle */ + int nArg, /* Number of SQL function arguments */ + const char *zName, /* Name of SQL function */ + void (**pxFunc)(sqlite3_context*,int,sqlite3_value**), /* OUT: Result */ + void **ppArg /* OUT: User data for *pxFunc */ ){ - if( sqlite3_stricmp("zipfile_cds", zName)==0 ){ - *pxFunc = zipfileFunctionCds; - *ppArg = (void*)pVtab; - return 1; - } - return 0; + if( sqlite3_stricmp("zipfile_cds", zName)==0 ){ + *pxFunc = zipfileFunctionCds; + *ppArg = (void*)pVtab; + return 1; + } + return 0; } typedef struct ZipfileBuffer ZipfileBuffer; struct ZipfileBuffer { - u8 *a; /* Pointer to buffer */ - int n; /* Size of buffer in bytes */ - int nAlloc; /* Byte allocated at a[] */ + u8 *a; /* Pointer to buffer */ + int n; /* Size of buffer in bytes */ + int nAlloc; /* Byte allocated at a[] */ }; typedef struct ZipfileCtx ZipfileCtx; struct ZipfileCtx { - int nEntry; - ZipfileBuffer body; - ZipfileBuffer cds; + int nEntry; + ZipfileBuffer body; + ZipfileBuffer cds; }; static int zipfileBufferGrow(ZipfileBuffer *pBuf, int nByte){ - if( pBuf->n+nByte>pBuf->nAlloc ){ - u8 *aNew; - sqlite3_int64 nNew = pBuf->n ? pBuf->n*2 : 512; - int nReq = pBuf->n + nByte; + if( pBuf->n+nByte>pBuf->nAlloc ){ + u8 *aNew; + sqlite3_int64 nNew = pBuf->n ? pBuf->n*2 : 512; + int nReq = pBuf->n + nByte; - while( nNewa, nNew); - if( aNew==0 ) return SQLITE_NOMEM; - pBuf->a = aNew; - pBuf->nAlloc = (int)nNew; - } - return SQLITE_OK; + while( nNewa, nNew); + if( aNew==0 ) return SQLITE_NOMEM; + pBuf->a = aNew; + pBuf->nAlloc = (int)nNew; + } + return SQLITE_OK; } /* @@ -8678,209 +8678,209 @@ static int zipfileBufferGrow(ZipfileBuffer *pBuf, int nByte){ ** SELECT zipfile(name,mode,mtime,data,method) ... */ void zipfileStep(sqlite3_context *pCtx, int nVal, sqlite3_value **apVal){ - ZipfileCtx *p; /* Aggregate function context */ - ZipfileEntry e; /* New entry to add to zip archive */ - - sqlite3_value *pName = 0; - sqlite3_value *pMode = 0; - sqlite3_value *pMtime = 0; - sqlite3_value *pData = 0; - sqlite3_value *pMethod = 0; - - int bIsDir = 0; - u32 mode; - int rc = SQLITE_OK; - char *zErr = 0; - - int iMethod = -1; /* Compression method to use (0 or 8) */ - - const u8 *aData = 0; /* Possibly compressed data for new entry */ - int nData = 0; /* Size of aData[] in bytes */ - int szUncompressed = 0; /* Size of data before compression */ - u8 *aFree = 0; /* Free this before returning */ - u32 iCrc32 = 0; /* crc32 of uncompressed data */ - - char *zName = 0; /* Path (name) of new entry */ - int nName = 0; /* Size of zName in bytes */ - char *zFree = 0; /* Free this before returning */ - int nByte; - - memset(&e, 0, sizeof(e)); - p = (ZipfileCtx*)sqlite3_aggregate_context(pCtx, sizeof(ZipfileCtx)); - if( p==0 ) return; - - /* Martial the arguments into stack variables */ - if( nVal!=2 && nVal!=4 && nVal!=5 ){ - zErr = sqlite3_mprintf("wrong number of arguments to function zipfile()"); - rc = SQLITE_ERROR; - goto zipfile_step_out; - } - pName = apVal[0]; - if( nVal==2 ){ - pData = apVal[1]; - }else{ - pMode = apVal[1]; - pMtime = apVal[2]; - pData = apVal[3]; - if( nVal==5 ){ - pMethod = apVal[4]; - } - } - - /* Check that the 'name' parameter looks ok. */ - zName = (char*)sqlite3_value_text(pName); - nName = sqlite3_value_bytes(pName); - if( zName==0 ){ - zErr = sqlite3_mprintf("first argument to zipfile() must be non-NULL"); - rc = SQLITE_ERROR; - goto zipfile_step_out; - } - - /* Inspect the 'method' parameter. This must be either 0 (store), 8 (use + ZipfileCtx *p; /* Aggregate function context */ + ZipfileEntry e; /* New entry to add to zip archive */ + + sqlite3_value *pName = 0; + sqlite3_value *pMode = 0; + sqlite3_value *pMtime = 0; + sqlite3_value *pData = 0; + sqlite3_value *pMethod = 0; + + int bIsDir = 0; + u32 mode; + int rc = SQLITE_OK; + char *zErr = 0; + + int iMethod = -1; /* Compression method to use (0 or 8) */ + + const u8 *aData = 0; /* Possibly compressed data for new entry */ + int nData = 0; /* Size of aData[] in bytes */ + int szUncompressed = 0; /* Size of data before compression */ + u8 *aFree = 0; /* Free this before returning */ + u32 iCrc32 = 0; /* crc32 of uncompressed data */ + + char *zName = 0; /* Path (name) of new entry */ + int nName = 0; /* Size of zName in bytes */ + char *zFree = 0; /* Free this before returning */ + int nByte; + + memset(&e, 0, sizeof(e)); + p = (ZipfileCtx*)sqlite3_aggregate_context(pCtx, sizeof(ZipfileCtx)); + if( p==0 ) return; + + /* Martial the arguments into stack variables */ + if( nVal!=2 && nVal!=4 && nVal!=5 ){ + zErr = sqlite3_mprintf("wrong number of arguments to function zipfile()"); + rc = SQLITE_ERROR; + goto zipfile_step_out; + } + pName = apVal[0]; + if( nVal==2 ){ + pData = apVal[1]; + }else{ + pMode = apVal[1]; + pMtime = apVal[2]; + pData = apVal[3]; + if( nVal==5 ){ + pMethod = apVal[4]; + } + } + + /* Check that the 'name' parameter looks ok. */ + zName = (char*)sqlite3_value_text(pName); + nName = sqlite3_value_bytes(pName); + if( zName==0 ){ + zErr = sqlite3_mprintf("first argument to zipfile() must be non-NULL"); + rc = SQLITE_ERROR; + goto zipfile_step_out; + } + + /* Inspect the 'method' parameter. This must be either 0 (store), 8 (use ** deflate compression) or NULL (choose automatically). */ - if( pMethod && SQLITE_NULL!=sqlite3_value_type(pMethod) ){ - iMethod = (int)sqlite3_value_int64(pMethod); - if( iMethod!=0 && iMethod!=8 ){ - zErr = sqlite3_mprintf("illegal method value: %d", iMethod); - rc = SQLITE_ERROR; - goto zipfile_step_out; - } + if( pMethod && SQLITE_NULL!=sqlite3_value_type(pMethod) ){ + iMethod = (int)sqlite3_value_int64(pMethod); + if( iMethod!=0 && iMethod!=8 ){ + zErr = sqlite3_mprintf("illegal method value: %d", iMethod); + rc = SQLITE_ERROR; + goto zipfile_step_out; } + } - /* Now inspect the data. If this is NULL, then the new entry must be a + /* Now inspect the data. If this is NULL, then the new entry must be a ** directory. Otherwise, figure out whether or not the data should ** be deflated or simply stored in the zip archive. */ - if( sqlite3_value_type(pData)==SQLITE_NULL ){ - bIsDir = 1; + if( sqlite3_value_type(pData)==SQLITE_NULL ){ + bIsDir = 1; + iMethod = 0; + }else{ + aData = sqlite3_value_blob(pData); + szUncompressed = nData = sqlite3_value_bytes(pData); + iCrc32 = crc32(0, aData, nData); + if( iMethod<0 || iMethod==8 ){ + int nOut = 0; + rc = zipfileDeflate(aData, nData, &aFree, &nOut, &zErr); + if( rc!=SQLITE_OK ){ + goto zipfile_step_out; + } + if( iMethod==8 || nOut0 && zName[nName-1]=='/' ){ - zErr = sqlite3_mprintf("non-directory name must not end with /"); - rc = SQLITE_ERROR; - goto zipfile_step_out; - } + if( bIsDir==0 ){ + if( nName>0 && zName[nName-1]=='/' ){ + zErr = sqlite3_mprintf("non-directory name must not end with /"); + rc = SQLITE_ERROR; + goto zipfile_step_out; + } + }else{ + if( nName==0 || zName[nName-1]!='/' ){ + zName = zFree = sqlite3_mprintf("%s/", zName); + if( zName==0 ){ + rc = SQLITE_NOMEM; + goto zipfile_step_out; + } + nName = (int)strlen(zName); }else{ - if( nName==0 || zName[nName-1]!='/' ){ - zName = zFree = sqlite3_mprintf("%s/", zName); - if( zName==0 ){ - rc = SQLITE_NOMEM; - goto zipfile_step_out; - } - nName = (int)strlen(zName); - }else{ - while( nName>1 && zName[nName-2]=='/' ) nName--; - } - } - - /* Assemble the ZipfileEntry object for the new zip archive entry */ - e.cds.iVersionMadeBy = ZIPFILE_NEWENTRY_MADEBY; - e.cds.iVersionExtract = ZIPFILE_NEWENTRY_REQUIRED; - e.cds.flags = ZIPFILE_NEWENTRY_FLAGS; - e.cds.iCompression = (u16)iMethod; - zipfileMtimeToDos(&e.cds, (u32)e.mUnixTime); - e.cds.crc32 = iCrc32; - e.cds.szCompressed = nData; - e.cds.szUncompressed = szUncompressed; - e.cds.iExternalAttr = (mode<<16); - e.cds.iOffset = p->body.n; - e.cds.nFile = (u16)nName; - e.cds.zFile = zName; - - /* Append the LFH to the body of the new archive */ - nByte = ZIPFILE_LFH_FIXED_SZ + e.cds.nFile + 9; - if( (rc = zipfileBufferGrow(&p->body, nByte)) ) goto zipfile_step_out; - p->body.n += zipfileSerializeLFH(&e, &p->body.a[p->body.n]); - - /* Append the data to the body of the new archive */ - if( nData>0 ){ - if( (rc = zipfileBufferGrow(&p->body, nData)) ) goto zipfile_step_out; - memcpy(&p->body.a[p->body.n], aData, nData); - p->body.n += nData; - } - - /* Append the CDS record to the directory of the new archive */ - nByte = ZIPFILE_CDS_FIXED_SZ + e.cds.nFile + 9; - if( (rc = zipfileBufferGrow(&p->cds, nByte)) ) goto zipfile_step_out; - p->cds.n += zipfileSerializeCDS(&e, &p->cds.a[p->cds.n]); - - /* Increment the count of entries in the archive */ - p->nEntry++; - -zipfile_step_out: - sqlite3_free(aFree); - sqlite3_free(zFree); - if( rc ){ - if( zErr ){ - sqlite3_result_error(pCtx, zErr, -1); - }else{ - sqlite3_result_error_code(pCtx, rc); - } + while( nName>1 && zName[nName-2]=='/' ) nName--; + } + } + + /* Assemble the ZipfileEntry object for the new zip archive entry */ + e.cds.iVersionMadeBy = ZIPFILE_NEWENTRY_MADEBY; + e.cds.iVersionExtract = ZIPFILE_NEWENTRY_REQUIRED; + e.cds.flags = ZIPFILE_NEWENTRY_FLAGS; + e.cds.iCompression = (u16)iMethod; + zipfileMtimeToDos(&e.cds, (u32)e.mUnixTime); + e.cds.crc32 = iCrc32; + e.cds.szCompressed = nData; + e.cds.szUncompressed = szUncompressed; + e.cds.iExternalAttr = (mode<<16); + e.cds.iOffset = p->body.n; + e.cds.nFile = (u16)nName; + e.cds.zFile = zName; + + /* Append the LFH to the body of the new archive */ + nByte = ZIPFILE_LFH_FIXED_SZ + e.cds.nFile + 9; + if( (rc = zipfileBufferGrow(&p->body, nByte)) ) goto zipfile_step_out; + p->body.n += zipfileSerializeLFH(&e, &p->body.a[p->body.n]); + + /* Append the data to the body of the new archive */ + if( nData>0 ){ + if( (rc = zipfileBufferGrow(&p->body, nData)) ) goto zipfile_step_out; + memcpy(&p->body.a[p->body.n], aData, nData); + p->body.n += nData; + } + + /* Append the CDS record to the directory of the new archive */ + nByte = ZIPFILE_CDS_FIXED_SZ + e.cds.nFile + 9; + if( (rc = zipfileBufferGrow(&p->cds, nByte)) ) goto zipfile_step_out; + p->cds.n += zipfileSerializeCDS(&e, &p->cds.a[p->cds.n]); + + /* Increment the count of entries in the archive */ + p->nEntry++; + + zipfile_step_out: + sqlite3_free(aFree); + sqlite3_free(zFree); + if( rc ){ + if( zErr ){ + sqlite3_result_error(pCtx, zErr, -1); + }else{ + sqlite3_result_error_code(pCtx, rc); } - sqlite3_free(zErr); + } + sqlite3_free(zErr); } /* ** xFinalize() callback for zipfile aggregate function. */ void zipfileFinal(sqlite3_context *pCtx){ - ZipfileCtx *p; - ZipfileEOCD eocd; - sqlite3_int64 nZip; - u8 *aZip; - - p = (ZipfileCtx*)sqlite3_aggregate_context(pCtx, sizeof(ZipfileCtx)); - if( p==0 ) return; - if( p->nEntry>0 ){ - memset(&eocd, 0, sizeof(eocd)); - eocd.nEntry = (u16)p->nEntry; - eocd.nEntryTotal = (u16)p->nEntry; - eocd.nSize = p->cds.n; - eocd.iOffset = p->body.n; - - nZip = p->body.n + p->cds.n + ZIPFILE_EOCD_FIXED_SZ; - aZip = (u8*)sqlite3_malloc64(nZip); - if( aZip==0 ){ - sqlite3_result_error_nomem(pCtx); - }else{ - memcpy(aZip, p->body.a, p->body.n); - memcpy(&aZip[p->body.n], p->cds.a, p->cds.n); - zipfileSerializeEOCD(&eocd, &aZip[p->body.n + p->cds.n]); - sqlite3_result_blob(pCtx, aZip, (int)nZip, zipfileFree); - } + ZipfileCtx *p; + ZipfileEOCD eocd; + sqlite3_int64 nZip; + u8 *aZip; + + p = (ZipfileCtx*)sqlite3_aggregate_context(pCtx, sizeof(ZipfileCtx)); + if( p==0 ) return; + if( p->nEntry>0 ){ + memset(&eocd, 0, sizeof(eocd)); + eocd.nEntry = (u16)p->nEntry; + eocd.nEntryTotal = (u16)p->nEntry; + eocd.nSize = p->cds.n; + eocd.iOffset = p->body.n; + + nZip = p->body.n + p->cds.n + ZIPFILE_EOCD_FIXED_SZ; + aZip = (u8*)sqlite3_malloc64(nZip); + if( aZip==0 ){ + sqlite3_result_error_nomem(pCtx); + }else{ + memcpy(aZip, p->body.a, p->body.n); + memcpy(&aZip[p->body.n], p->cds.a, p->cds.n); + zipfileSerializeEOCD(&eocd, &aZip[p->body.n + p->cds.n]); + sqlite3_result_blob(pCtx, aZip, (int)nZip, zipfileFree); } + } - sqlite3_free(p->body.a); - sqlite3_free(p->cds.a); + sqlite3_free(p->body.a); + sqlite3_free(p->cds.a); } @@ -8888,41 +8888,41 @@ void zipfileFinal(sqlite3_context *pCtx){ ** Register the "zipfile" virtual table. */ static int zipfileRegister(sqlite3 *db){ - static sqlite3_module zipfileModule = { - 1, /* iVersion */ - zipfileConnect, /* xCreate */ - zipfileConnect, /* xConnect */ - zipfileBestIndex, /* xBestIndex */ - zipfileDisconnect, /* xDisconnect */ - zipfileDisconnect, /* xDestroy */ - zipfileOpen, /* xOpen - open a cursor */ - zipfileClose, /* xClose - close a cursor */ - zipfileFilter, /* xFilter - configure scan constraints */ - zipfileNext, /* xNext - advance a cursor */ - zipfileEof, /* xEof - check for end of scan */ - zipfileColumn, /* xColumn - read data */ - 0, /* xRowid - read data */ - zipfileUpdate, /* xUpdate */ - zipfileBegin, /* xBegin */ - 0, /* xSync */ - zipfileCommit, /* xCommit */ - zipfileRollback, /* xRollback */ - zipfileFindFunction, /* xFindMethod */ - 0, /* xRename */ - }; + static sqlite3_module zipfileModule = { + 1, /* iVersion */ + zipfileConnect, /* xCreate */ + zipfileConnect, /* xConnect */ + zipfileBestIndex, /* xBestIndex */ + zipfileDisconnect, /* xDisconnect */ + zipfileDisconnect, /* xDestroy */ + zipfileOpen, /* xOpen - open a cursor */ + zipfileClose, /* xClose - close a cursor */ + zipfileFilter, /* xFilter - configure scan constraints */ + zipfileNext, /* xNext - advance a cursor */ + zipfileEof, /* xEof - check for end of scan */ + zipfileColumn, /* xColumn - read data */ + 0, /* xRowid - read data */ + zipfileUpdate, /* xUpdate */ + zipfileBegin, /* xBegin */ + 0, /* xSync */ + zipfileCommit, /* xCommit */ + zipfileRollback, /* xRollback */ + zipfileFindFunction, /* xFindMethod */ + 0, /* xRename */ + }; - int rc = sqlite3_create_module(db, "zipfile" , &zipfileModule, 0); - if( rc==SQLITE_OK ) rc = sqlite3_overload_function(db, "zipfile_cds", -1); - if( rc==SQLITE_OK ){ - rc = sqlite3_create_function(db, "zipfile", -1, SQLITE_UTF8, 0, 0, - zipfileStep, zipfileFinal - ); - } - assert( sizeof(i64)==8 ); - assert( sizeof(u32)==4 ); - assert( sizeof(u16)==2 ); - assert( sizeof(u8)==1 ); - return rc; + int rc = sqlite3_create_module(db, "zipfile" , &zipfileModule, 0); + if( rc==SQLITE_OK ) rc = sqlite3_overload_function(db, "zipfile_cds", -1); + if( rc==SQLITE_OK ){ + rc = sqlite3_create_function(db, "zipfile", -1, SQLITE_UTF8, 0, 0, + zipfileStep, zipfileFinal + ); + } + assert( sizeof(i64)==8 ); + assert( sizeof(u32)==4 ); + assert( sizeof(u16)==2 ); + assert( sizeof(u8)==1 ); + return rc; } #else /* SQLITE_OMIT_VIRTUALTABLE */ # define zipfileRegister(x) SQLITE_OK @@ -8932,13 +8932,13 @@ static int zipfileRegister(sqlite3 *db){ #endif int sqlite3_zipfile_init( - sqlite3 *db, - char **pzErrMsg, - const sqlite3_api_routines *pApi + sqlite3 *db, + char **pzErrMsg, + const sqlite3_api_routines *pApi ){ - SQLITE_EXTENSION_INIT2(pApi); - (void)pzErrMsg; /* Unused parameter */ - return zipfileRegister(db); + SQLITE_EXTENSION_INIT2(pApi); + (void)pzErrMsg; /* Unused parameter */ + return zipfileRegister(db); } /************************* End ../ext/misc/zipfile.c ********************/ @@ -8980,34 +8980,34 @@ SQLITE_EXTENSION_INIT1 ** compressed data. */ static void sqlarCompressFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv + sqlite3_context *context, + int argc, + sqlite3_value **argv ){ - assert( argc==1 ); - if( sqlite3_value_type(argv[0])==SQLITE_BLOB ){ - const Bytef *pData = sqlite3_value_blob(argv[0]); - uLong nData = sqlite3_value_bytes(argv[0]); - uLongf nOut = compressBound(nData); - Bytef *pOut; - - pOut = (Bytef*)sqlite3_malloc(nOut); - if( pOut==0 ){ - sqlite3_result_error_nomem(context); - return; - }else{ - if( Z_OK!=compress(pOut, &nOut, pData, nData) ){ - sqlite3_result_error(context, "error in compress()", -1); - }else if( nOut DESC */ - IdxConstraint *pNext; /* Next constraint in pEq or pRange list */ - IdxConstraint *pLink; /* See above */ + char *zColl; /* Collation sequence */ + int bRange; /* True for range, false for eq */ + int iCol; /* Constrained table column */ + int bFlag; /* Used by idxFindCompatible() */ + int bDesc; /* True if ORDER BY DESC */ + IdxConstraint *pNext; /* Next constraint in pEq or pRange list */ + IdxConstraint *pLink; /* See above */ }; /* ** A single scan of a single table. */ struct IdxScan { - IdxTable *pTab; /* Associated table object */ - int iDb; /* Database containing table zTable */ - i64 covering; /* Mask of columns required for cov. index */ - IdxConstraint *pOrder; /* ORDER BY columns */ - IdxConstraint *pEq; /* List of == constraints */ - IdxConstraint *pRange; /* List of < constraints */ - IdxScan *pNextScan; /* Next IdxScan object for same analysis */ + IdxTable *pTab; /* Associated table object */ + int iDb; /* Database containing table zTable */ + i64 covering; /* Mask of columns required for cov. index */ + IdxConstraint *pOrder; /* ORDER BY columns */ + IdxConstraint *pEq; /* List of == constraints */ + IdxConstraint *pRange; /* List of < constraints */ + IdxScan *pNextScan; /* Next IdxScan object for same analysis */ }; /* -** Information regarding a single database table. Extracted from +** Information regarding a single database table. Extracted from ** "PRAGMA table_info" by function idxGetTableInfo(). */ struct IdxColumn { - char *zName; - char *zColl; - int iPk; + char *zName; + char *zColl; + int iPk; }; struct IdxTable { - int nCol; - char *zName; /* Table name */ - IdxColumn *aCol; - IdxTable *pNext; /* Next table in linked list of all tables */ + int nCol; + char *zName; /* Table name */ + IdxColumn *aCol; + IdxTable *pNext; /* Next table in linked list of all tables */ }; /* @@ -9350,9 +9350,9 @@ struct IdxTable { ** sqlite3expert.pWrite. */ struct IdxWrite { - IdxTable *pTab; - int eOp; /* SQLITE_UPDATE, DELETE or INSERT */ - IdxWrite *pNext; + IdxTable *pTab; + int eOp; /* SQLITE_UPDATE, DELETE or INSERT */ + IdxWrite *pNext; }; /* @@ -9360,11 +9360,11 @@ struct IdxWrite { ** structure. */ struct IdxStatement { - int iId; /* Statement number */ - char *zSql; /* SQL statement */ - char *zIdx; /* Indexes */ - char *zEQP; /* Plan */ - IdxStatement *pNext; + int iId; /* Statement number */ + char *zSql; /* SQL statement */ + char *zIdx; /* Indexes */ + char *zEQP; /* Plan */ + IdxStatement *pNext; }; @@ -9381,76 +9381,76 @@ struct IdxStatement { typedef struct IdxHashEntry IdxHashEntry; typedef struct IdxHash IdxHash; struct IdxHashEntry { - char *zKey; /* nul-terminated key */ - char *zVal; /* nul-terminated value string */ - char *zVal2; /* nul-terminated value string 2 */ - IdxHashEntry *pHashNext; /* Next entry in same hash bucket */ - IdxHashEntry *pNext; /* Next entry in hash */ + char *zKey; /* nul-terminated key */ + char *zVal; /* nul-terminated value string */ + char *zVal2; /* nul-terminated value string 2 */ + IdxHashEntry *pHashNext; /* Next entry in same hash bucket */ + IdxHashEntry *pNext; /* Next entry in hash */ }; struct IdxHash { - IdxHashEntry *pFirst; - IdxHashEntry *aHash[IDX_HASH_SIZE]; + IdxHashEntry *pFirst; + IdxHashEntry *aHash[IDX_HASH_SIZE]; }; /* ** sqlite3expert object. */ struct sqlite3expert { - int iSample; /* Percentage of tables to sample for stat1 */ - sqlite3 *db; /* User database */ - sqlite3 *dbm; /* In-memory db for this analysis */ - sqlite3 *dbv; /* Vtab schema for this analysis */ - IdxTable *pTable; /* List of all IdxTable objects */ - IdxScan *pScan; /* List of scan objects */ - IdxWrite *pWrite; /* List of write objects */ - IdxStatement *pStatement; /* List of IdxStatement objects */ - int bRun; /* True once analysis has run */ - char **pzErrmsg; - int rc; /* Error code from whereinfo hook */ - IdxHash hIdx; /* Hash containing all candidate indexes */ - char *zCandidates; /* For EXPERT_REPORT_CANDIDATES */ + int iSample; /* Percentage of tables to sample for stat1 */ + sqlite3 *db; /* User database */ + sqlite3 *dbm; /* In-memory db for this analysis */ + sqlite3 *dbv; /* Vtab schema for this analysis */ + IdxTable *pTable; /* List of all IdxTable objects */ + IdxScan *pScan; /* List of scan objects */ + IdxWrite *pWrite; /* List of write objects */ + IdxStatement *pStatement; /* List of IdxStatement objects */ + int bRun; /* True once analysis has run */ + char **pzErrmsg; + int rc; /* Error code from whereinfo hook */ + IdxHash hIdx; /* Hash containing all candidate indexes */ + char *zCandidates; /* For EXPERT_REPORT_CANDIDATES */ }; /* -** Allocate and return nByte bytes of zeroed memory using sqlite3_malloc(). +** Allocate and return nByte bytes of zeroed memory using sqlite3_malloc(). ** If the allocation fails, set *pRc to SQLITE_NOMEM and return NULL. */ static void *idxMalloc(int *pRc, int nByte){ - void *pRet; - assert( *pRc==SQLITE_OK ); - assert( nByte>0 ); - pRet = sqlite3_malloc(nByte); - if( pRet ){ - memset(pRet, 0, nByte); - }else{ - *pRc = SQLITE_NOMEM; - } - return pRet; + void *pRet; + assert( *pRc==SQLITE_OK ); + assert( nByte>0 ); + pRet = sqlite3_malloc(nByte); + if( pRet ){ + memset(pRet, 0, nByte); + }else{ + *pRc = SQLITE_NOMEM; + } + return pRet; } /* ** Initialize an IdxHash hash table. */ static void idxHashInit(IdxHash *pHash){ - memset(pHash, 0, sizeof(IdxHash)); + memset(pHash, 0, sizeof(IdxHash)); } /* ** Reset an IdxHash hash table. */ static void idxHashClear(IdxHash *pHash){ - int i; - for(i=0; iaHash[i]; pEntry; pEntry=pNext){ - pNext = pEntry->pHashNext; - sqlite3_free(pEntry->zVal2); - sqlite3_free(pEntry); - } + int i; + for(i=0; iaHash[i]; pEntry; pEntry=pNext){ + pNext = pEntry->pHashNext; + sqlite3_free(pEntry->zVal2); + sqlite3_free(pEntry); } - memset(pHash, 0, sizeof(IdxHash)); + } + memset(pHash, 0, sizeof(IdxHash)); } /* @@ -9458,68 +9458,68 @@ static void idxHashClear(IdxHash *pHash){ ** arguments to this function belongs. */ static int idxHashString(const char *z, int n){ - unsigned int ret = 0; - int i; - for(i=0; i=0 ); - for(pEntry=pHash->aHash[iHash]; pEntry; pEntry=pEntry->pHashNext){ - if( STRLEN(pEntry->zKey)==nKey && 0==memcmp(pEntry->zKey, zKey, nKey) ){ - return 1; - } - } - pEntry = idxMalloc(pRc, sizeof(IdxHashEntry) + nKey+1 + nVal+1); - if( pEntry ){ - pEntry->zKey = (char*)&pEntry[1]; - memcpy(pEntry->zKey, zKey, nKey); - if( zVal ){ - pEntry->zVal = &pEntry->zKey[nKey+1]; - memcpy(pEntry->zVal, zVal, nVal); - } - pEntry->pHashNext = pHash->aHash[iHash]; - pHash->aHash[iHash] = pEntry; - - pEntry->pNext = pHash->pFirst; - pHash->pFirst = pEntry; - } - return 0; -} - -/* -** If zKey/nKey is present in the hash table, return a pointer to the + int nKey = STRLEN(zKey); + int iHash = idxHashString(zKey, nKey); + int nVal = (zVal ? STRLEN(zVal) : 0); + IdxHashEntry *pEntry; + assert( iHash>=0 ); + for(pEntry=pHash->aHash[iHash]; pEntry; pEntry=pEntry->pHashNext){ + if( STRLEN(pEntry->zKey)==nKey && 0==memcmp(pEntry->zKey, zKey, nKey) ){ + return 1; + } + } + pEntry = idxMalloc(pRc, sizeof(IdxHashEntry) + nKey+1 + nVal+1); + if( pEntry ){ + pEntry->zKey = (char*)&pEntry[1]; + memcpy(pEntry->zKey, zKey, nKey); + if( zVal ){ + pEntry->zVal = &pEntry->zKey[nKey+1]; + memcpy(pEntry->zVal, zVal, nVal); + } + pEntry->pHashNext = pHash->aHash[iHash]; + pHash->aHash[iHash] = pEntry; + + pEntry->pNext = pHash->pFirst; + pHash->pFirst = pEntry; + } + return 0; +} + +/* +** If zKey/nKey is present in the hash table, return a pointer to the ** hash-entry object. */ static IdxHashEntry *idxHashFind(IdxHash *pHash, const char *zKey, int nKey){ - int iHash; - IdxHashEntry *pEntry; - if( nKey<0 ) nKey = STRLEN(zKey); - iHash = idxHashString(zKey, nKey); - assert( iHash>=0 ); - for(pEntry=pHash->aHash[iHash]; pEntry; pEntry=pEntry->pHashNext){ - if( STRLEN(pEntry->zKey)==nKey && 0==memcmp(pEntry->zKey, zKey, nKey) ){ - return pEntry; - } + int iHash; + IdxHashEntry *pEntry; + if( nKey<0 ) nKey = STRLEN(zKey); + iHash = idxHashString(zKey, nKey); + assert( iHash>=0 ); + for(pEntry=pHash->aHash[iHash]; pEntry; pEntry=pEntry->pHashNext){ + if( STRLEN(pEntry->zKey)==nKey && 0==memcmp(pEntry->zKey, zKey, nKey) ){ + return pEntry; } - return 0; + } + return 0; } /* @@ -9529,9 +9529,9 @@ static IdxHashEntry *idxHashFind(IdxHash *pHash, const char *zKey, int nKey){ ** hash table, return NULL. */ static const char *idxHashSearch(IdxHash *pHash, const char *zKey, int nKey){ - IdxHashEntry *pEntry = idxHashFind(pHash, zKey, nKey); - if( pEntry ) return pEntry->zVal; - return 0; + IdxHashEntry *pEntry = idxHashFind(pHash, zKey, nKey); + if( pEntry ) return pEntry->zVal; + return 0; } /* @@ -9539,16 +9539,16 @@ static const char *idxHashSearch(IdxHash *pHash, const char *zKey, int nKey){ ** variable to point to a copy of nul-terminated string zColl. */ static IdxConstraint *idxNewConstraint(int *pRc, const char *zColl){ - IdxConstraint *pNew; - int nColl = STRLEN(zColl); + IdxConstraint *pNew; + int nColl = STRLEN(zColl); - assert( *pRc==SQLITE_OK ); - pNew = (IdxConstraint*)idxMalloc(pRc, sizeof(IdxConstraint) * nColl + 1); - if( pNew ){ - pNew->zColl = (char*)&pNew[1]; - memcpy(pNew->zColl, zColl, nColl+1); - } - return pNew; + assert( *pRc==SQLITE_OK ); + pNew = (IdxConstraint*)idxMalloc(pRc, sizeof(IdxConstraint) * nColl + 1); + if( pNew ){ + pNew->zColl = (char*)&pNew[1]; + memcpy(pNew->zColl, zColl, nColl+1); + } + return pNew; } /* @@ -9556,52 +9556,52 @@ static IdxConstraint *idxNewConstraint(int *pRc, const char *zColl){ ** the error message to callback function xOut. */ static void idxDatabaseError( - sqlite3 *db, /* Database handle */ - char **pzErrmsg /* Write error here */ + sqlite3 *db, /* Database handle */ + char **pzErrmsg /* Write error here */ ){ - *pzErrmsg = sqlite3_mprintf("%s", sqlite3_errmsg(db)); + *pzErrmsg = sqlite3_mprintf("%s", sqlite3_errmsg(db)); } /* ** Prepare an SQL statement. */ static int idxPrepareStmt( - sqlite3 *db, /* Database handle to compile against */ - sqlite3_stmt **ppStmt, /* OUT: Compiled SQL statement */ - char **pzErrmsg, /* OUT: sqlite3_malloc()ed error message */ - const char *zSql /* SQL statement to compile */ + sqlite3 *db, /* Database handle to compile against */ + sqlite3_stmt **ppStmt, /* OUT: Compiled SQL statement */ + char **pzErrmsg, /* OUT: sqlite3_malloc()ed error message */ + const char *zSql /* SQL statement to compile */ ){ - int rc = sqlite3_prepare_v2(db, zSql, -1, ppStmt, 0); - if( rc!=SQLITE_OK ){ - *ppStmt = 0; - idxDatabaseError(db, pzErrmsg); - } - return rc; + int rc = sqlite3_prepare_v2(db, zSql, -1, ppStmt, 0); + if( rc!=SQLITE_OK ){ + *ppStmt = 0; + idxDatabaseError(db, pzErrmsg); + } + return rc; } /* ** Prepare an SQL statement using the results of a printf() formatting. */ static int idxPrintfPrepareStmt( - sqlite3 *db, /* Database handle to compile against */ - sqlite3_stmt **ppStmt, /* OUT: Compiled SQL statement */ - char **pzErrmsg, /* OUT: sqlite3_malloc()ed error message */ - const char *zFmt, /* printf() format of SQL statement */ - ... /* Trailing printf() arguments */ + sqlite3 *db, /* Database handle to compile against */ + sqlite3_stmt **ppStmt, /* OUT: Compiled SQL statement */ + char **pzErrmsg, /* OUT: sqlite3_malloc()ed error message */ + const char *zFmt, /* printf() format of SQL statement */ + ... /* Trailing printf() arguments */ ){ - va_list ap; - int rc; - char *zSql; - va_start(ap, zFmt); - zSql = sqlite3_vmprintf(zFmt, ap); - if( zSql==0 ){ - rc = SQLITE_NOMEM; - }else{ - rc = idxPrepareStmt(db, ppStmt, pzErrmsg, zSql); - sqlite3_free(zSql); - } - va_end(ap); - return rc; + va_list ap; + int rc; + char *zSql; + va_start(ap, zFmt); + zSql = sqlite3_vmprintf(zFmt, ap); + if( zSql==0 ){ + rc = SQLITE_NOMEM; + }else{ + rc = idxPrepareStmt(db, ppStmt, pzErrmsg, zSql); + sqlite3_free(zSql); + } + va_end(ap); + return rc; } @@ -9610,41 +9610,41 @@ static int idxPrintfPrepareStmt( */ typedef struct ExpertVtab ExpertVtab; struct ExpertVtab { - sqlite3_vtab base; - IdxTable *pTab; - sqlite3expert *pExpert; + sqlite3_vtab base; + IdxTable *pTab; + sqlite3expert *pExpert; }; typedef struct ExpertCsr ExpertCsr; struct ExpertCsr { - sqlite3_vtab_cursor base; - sqlite3_stmt *pData; + sqlite3_vtab_cursor base; + sqlite3_stmt *pData; }; static char *expertDequote(const char *zIn){ - int n = STRLEN(zIn); - char *zRet = sqlite3_malloc(n); - - assert( zIn[0]=='\'' ); - assert( zIn[n-1]=='\'' ); - - if( zRet ){ - int iOut = 0; - int iIn = 0; - for(iIn=1; iIn<(n-1); iIn++){ - if( zIn[iIn]=='\'' ){ - assert( zIn[iIn+1]=='\'' ); - iIn++; - } - zRet[iOut++] = zIn[iIn]; - } - zRet[iOut] = '\0'; + int n = STRLEN(zIn); + char *zRet = sqlite3_malloc(n); + + assert( zIn[0]=='\'' ); + assert( zIn[n-1]=='\'' ); + + if( zRet ){ + int iOut = 0; + int iIn = 0; + for(iIn=1; iIn<(n-1); iIn++){ + if( zIn[iIn]=='\'' ){ + assert( zIn[iIn+1]=='\'' ); + iIn++; + } + zRet[iOut++] = zIn[iIn]; } + zRet[iOut] = '\0'; + } - return zRet; + return zRet; } -/* +/* ** This function is the implementation of both the xConnect and xCreate ** methods of the r-tree virtual table. ** @@ -9654,261 +9654,261 @@ static char *expertDequote(const char *zIn){ ** argv[...] -> column names... */ static int expertConnect( - sqlite3 *db, - void *pAux, - int argc, const char *const*argv, - sqlite3_vtab **ppVtab, - char **pzErr + sqlite3 *db, + void *pAux, + int argc, const char *const*argv, + sqlite3_vtab **ppVtab, + char **pzErr ){ - sqlite3expert *pExpert = (sqlite3expert*)pAux; - ExpertVtab *p = 0; - int rc; - - if( argc!=4 ){ - *pzErr = sqlite3_mprintf("internal error!"); - rc = SQLITE_ERROR; + sqlite3expert *pExpert = (sqlite3expert*)pAux; + ExpertVtab *p = 0; + int rc; + + if( argc!=4 ){ + *pzErr = sqlite3_mprintf("internal error!"); + rc = SQLITE_ERROR; + }else{ + char *zCreateTable = expertDequote(argv[3]); + if( zCreateTable ){ + rc = sqlite3_declare_vtab(db, zCreateTable); + if( rc==SQLITE_OK ){ + p = idxMalloc(&rc, sizeof(ExpertVtab)); + } + if( rc==SQLITE_OK ){ + p->pExpert = pExpert; + p->pTab = pExpert->pTable; + assert( sqlite3_stricmp(p->pTab->zName, argv[2])==0 ); + } + sqlite3_free(zCreateTable); }else{ - char *zCreateTable = expertDequote(argv[3]); - if( zCreateTable ){ - rc = sqlite3_declare_vtab(db, zCreateTable); - if( rc==SQLITE_OK ){ - p = idxMalloc(&rc, sizeof(ExpertVtab)); - } - if( rc==SQLITE_OK ){ - p->pExpert = pExpert; - p->pTab = pExpert->pTable; - assert( sqlite3_stricmp(p->pTab->zName, argv[2])==0 ); - } - sqlite3_free(zCreateTable); - }else{ - rc = SQLITE_NOMEM; - } + rc = SQLITE_NOMEM; } + } - *ppVtab = (sqlite3_vtab*)p; - return rc; + *ppVtab = (sqlite3_vtab*)p; + return rc; } static int expertDisconnect(sqlite3_vtab *pVtab){ - ExpertVtab *p = (ExpertVtab*)pVtab; - sqlite3_free(p); - return SQLITE_OK; + ExpertVtab *p = (ExpertVtab*)pVtab; + sqlite3_free(p); + return SQLITE_OK; } static int expertBestIndex(sqlite3_vtab *pVtab, sqlite3_index_info *pIdxInfo){ - ExpertVtab *p = (ExpertVtab*)pVtab; - int rc = SQLITE_OK; - int n = 0; - IdxScan *pScan; - const int opmask = - SQLITE_INDEX_CONSTRAINT_EQ | SQLITE_INDEX_CONSTRAINT_GT | - SQLITE_INDEX_CONSTRAINT_LT | SQLITE_INDEX_CONSTRAINT_GE | - SQLITE_INDEX_CONSTRAINT_LE; - - pScan = idxMalloc(&rc, sizeof(IdxScan)); - if( pScan ){ - int i; - - /* Link the new scan object into the list */ - pScan->pTab = p->pTab; - pScan->pNextScan = p->pExpert->pScan; - p->pExpert->pScan = pScan; - - /* Add the constraints to the IdxScan object */ - for(i=0; inConstraint; i++){ - struct sqlite3_index_constraint *pCons = &pIdxInfo->aConstraint[i]; - if( pCons->usable - && pCons->iColumn>=0 - && p->pTab->aCol[pCons->iColumn].iPk==0 - && (pCons->op & opmask) - ){ - IdxConstraint *pNew; - const char *zColl = sqlite3_vtab_collation(pIdxInfo, i); - pNew = idxNewConstraint(&rc, zColl); - if( pNew ){ - pNew->iCol = pCons->iColumn; - if( pCons->op==SQLITE_INDEX_CONSTRAINT_EQ ){ - pNew->pNext = pScan->pEq; - pScan->pEq = pNew; - }else{ - pNew->bRange = 1; - pNew->pNext = pScan->pRange; - pScan->pRange = pNew; - } - } - n++; - pIdxInfo->aConstraintUsage[i].argvIndex = n; - } - } + ExpertVtab *p = (ExpertVtab*)pVtab; + int rc = SQLITE_OK; + int n = 0; + IdxScan *pScan; + const int opmask = + SQLITE_INDEX_CONSTRAINT_EQ | SQLITE_INDEX_CONSTRAINT_GT | + SQLITE_INDEX_CONSTRAINT_LT | SQLITE_INDEX_CONSTRAINT_GE | + SQLITE_INDEX_CONSTRAINT_LE; + + pScan = idxMalloc(&rc, sizeof(IdxScan)); + if( pScan ){ + int i; - /* Add the ORDER BY to the IdxScan object */ - for(i=pIdxInfo->nOrderBy-1; i>=0; i--){ - int iCol = pIdxInfo->aOrderBy[i].iColumn; - if( iCol>=0 ){ - IdxConstraint *pNew = idxNewConstraint(&rc, p->pTab->aCol[iCol].zColl); - if( pNew ){ - pNew->iCol = iCol; - pNew->bDesc = pIdxInfo->aOrderBy[i].desc; - pNew->pNext = pScan->pOrder; - pNew->pLink = pScan->pOrder; - pScan->pOrder = pNew; - n++; - } - } - } - } + /* Link the new scan object into the list */ + pScan->pTab = p->pTab; + pScan->pNextScan = p->pExpert->pScan; + p->pExpert->pScan = pScan; - pIdxInfo->estimatedCost = 1000000.0 / (n+1); - return rc; + /* Add the constraints to the IdxScan object */ + for(i=0; inConstraint; i++){ + struct sqlite3_index_constraint *pCons = &pIdxInfo->aConstraint[i]; + if( pCons->usable + && pCons->iColumn>=0 + && p->pTab->aCol[pCons->iColumn].iPk==0 + && (pCons->op & opmask) + ){ + IdxConstraint *pNew; + const char *zColl = sqlite3_vtab_collation(pIdxInfo, i); + pNew = idxNewConstraint(&rc, zColl); + if( pNew ){ + pNew->iCol = pCons->iColumn; + if( pCons->op==SQLITE_INDEX_CONSTRAINT_EQ ){ + pNew->pNext = pScan->pEq; + pScan->pEq = pNew; + }else{ + pNew->bRange = 1; + pNew->pNext = pScan->pRange; + pScan->pRange = pNew; + } + } + n++; + pIdxInfo->aConstraintUsage[i].argvIndex = n; + } + } + + /* Add the ORDER BY to the IdxScan object */ + for(i=pIdxInfo->nOrderBy-1; i>=0; i--){ + int iCol = pIdxInfo->aOrderBy[i].iColumn; + if( iCol>=0 ){ + IdxConstraint *pNew = idxNewConstraint(&rc, p->pTab->aCol[iCol].zColl); + if( pNew ){ + pNew->iCol = iCol; + pNew->bDesc = pIdxInfo->aOrderBy[i].desc; + pNew->pNext = pScan->pOrder; + pNew->pLink = pScan->pOrder; + pScan->pOrder = pNew; + n++; + } + } + } + } + + pIdxInfo->estimatedCost = 1000000.0 / (n+1); + return rc; } static int expertUpdate( - sqlite3_vtab *pVtab, - int nData, - sqlite3_value **azData, - sqlite_int64 *pRowid + sqlite3_vtab *pVtab, + int nData, + sqlite3_value **azData, + sqlite_int64 *pRowid ){ - (void)pVtab; - (void)nData; - (void)azData; - (void)pRowid; - return SQLITE_OK; + (void)pVtab; + (void)nData; + (void)azData; + (void)pRowid; + return SQLITE_OK; } -/* +/* ** Virtual table module xOpen method. */ static int expertOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){ - int rc = SQLITE_OK; - ExpertCsr *pCsr; - (void)pVTab; - pCsr = idxMalloc(&rc, sizeof(ExpertCsr)); - *ppCursor = (sqlite3_vtab_cursor*)pCsr; - return rc; + int rc = SQLITE_OK; + ExpertCsr *pCsr; + (void)pVTab; + pCsr = idxMalloc(&rc, sizeof(ExpertCsr)); + *ppCursor = (sqlite3_vtab_cursor*)pCsr; + return rc; } -/* +/* ** Virtual table module xClose method. */ static int expertClose(sqlite3_vtab_cursor *cur){ - ExpertCsr *pCsr = (ExpertCsr*)cur; - sqlite3_finalize(pCsr->pData); - sqlite3_free(pCsr); - return SQLITE_OK; + ExpertCsr *pCsr = (ExpertCsr*)cur; + sqlite3_finalize(pCsr->pData); + sqlite3_free(pCsr); + return SQLITE_OK; } /* ** Virtual table module xEof method. ** -** Return non-zero if the cursor does not currently point to a valid +** Return non-zero if the cursor does not currently point to a valid ** record (i.e if the scan has finished), or zero otherwise. */ static int expertEof(sqlite3_vtab_cursor *cur){ - ExpertCsr *pCsr = (ExpertCsr*)cur; - return pCsr->pData==0; + ExpertCsr *pCsr = (ExpertCsr*)cur; + return pCsr->pData==0; } -/* +/* ** Virtual table module xNext method. */ static int expertNext(sqlite3_vtab_cursor *cur){ - ExpertCsr *pCsr = (ExpertCsr*)cur; - int rc = SQLITE_OK; - - assert( pCsr->pData ); - rc = sqlite3_step(pCsr->pData); - if( rc!=SQLITE_ROW ){ - rc = sqlite3_finalize(pCsr->pData); - pCsr->pData = 0; - }else{ - rc = SQLITE_OK; - } + ExpertCsr *pCsr = (ExpertCsr*)cur; + int rc = SQLITE_OK; - return rc; + assert( pCsr->pData ); + rc = sqlite3_step(pCsr->pData); + if( rc!=SQLITE_ROW ){ + rc = sqlite3_finalize(pCsr->pData); + pCsr->pData = 0; + }else{ + rc = SQLITE_OK; + } + + return rc; } -/* +/* ** Virtual table module xRowid method. */ static int expertRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){ - (void)cur; - *pRowid = 0; - return SQLITE_OK; + (void)cur; + *pRowid = 0; + return SQLITE_OK; } -/* +/* ** Virtual table module xColumn method. */ static int expertColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){ - ExpertCsr *pCsr = (ExpertCsr*)cur; - sqlite3_value *pVal; - pVal = sqlite3_column_value(pCsr->pData, i); - if( pVal ){ - sqlite3_result_value(ctx, pVal); - } - return SQLITE_OK; + ExpertCsr *pCsr = (ExpertCsr*)cur; + sqlite3_value *pVal; + pVal = sqlite3_column_value(pCsr->pData, i); + if( pVal ){ + sqlite3_result_value(ctx, pVal); + } + return SQLITE_OK; } -/* +/* ** Virtual table module xFilter method. */ static int expertFilter( - sqlite3_vtab_cursor *cur, - int idxNum, const char *idxStr, - int argc, sqlite3_value **argv + sqlite3_vtab_cursor *cur, + int idxNum, const char *idxStr, + int argc, sqlite3_value **argv ){ - ExpertCsr *pCsr = (ExpertCsr*)cur; - ExpertVtab *pVtab = (ExpertVtab*)(cur->pVtab); - sqlite3expert *pExpert = pVtab->pExpert; - int rc; - - (void)idxNum; - (void)idxStr; - (void)argc; - (void)argv; - rc = sqlite3_finalize(pCsr->pData); - pCsr->pData = 0; - if( rc==SQLITE_OK ){ - rc = idxPrintfPrepareStmt(pExpert->db, &pCsr->pData, &pVtab->base.zErrMsg, - "SELECT * FROM main.%Q WHERE sample()", pVtab->pTab->zName - ); - } + ExpertCsr *pCsr = (ExpertCsr*)cur; + ExpertVtab *pVtab = (ExpertVtab*)(cur->pVtab); + sqlite3expert *pExpert = pVtab->pExpert; + int rc; + + (void)idxNum; + (void)idxStr; + (void)argc; + (void)argv; + rc = sqlite3_finalize(pCsr->pData); + pCsr->pData = 0; + if( rc==SQLITE_OK ){ + rc = idxPrintfPrepareStmt(pExpert->db, &pCsr->pData, &pVtab->base.zErrMsg, + "SELECT * FROM main.%Q WHERE sample()", pVtab->pTab->zName + ); + } - if( rc==SQLITE_OK ){ - rc = expertNext(cur); - } - return rc; + if( rc==SQLITE_OK ){ + rc = expertNext(cur); + } + return rc; } static int idxRegisterVtab(sqlite3expert *p){ - static sqlite3_module expertModule = { - 2, /* iVersion */ - expertConnect, /* xCreate - create a table */ - expertConnect, /* xConnect - connect to an existing table */ - expertBestIndex, /* xBestIndex - Determine search strategy */ - expertDisconnect, /* xDisconnect - Disconnect from a table */ - expertDisconnect, /* xDestroy - Drop a table */ - expertOpen, /* xOpen - open a cursor */ - expertClose, /* xClose - close a cursor */ - expertFilter, /* xFilter - configure scan constraints */ - expertNext, /* xNext - advance a cursor */ - expertEof, /* xEof */ - expertColumn, /* xColumn - read data */ - expertRowid, /* xRowid - read data */ - expertUpdate, /* xUpdate - write data */ - 0, /* xBegin - begin transaction */ - 0, /* xSync - sync transaction */ - 0, /* xCommit - commit transaction */ - 0, /* xRollback - rollback transaction */ - 0, /* xFindFunction - function overloading */ - 0, /* xRename - rename the table */ - 0, /* xSavepoint */ - 0, /* xRelease */ - 0, /* xRollbackTo */ - 0, /* xShadowName */ - }; - - return sqlite3_create_module(p->dbv, "expert", &expertModule, (void*)p); + static sqlite3_module expertModule = { + 2, /* iVersion */ + expertConnect, /* xCreate - create a table */ + expertConnect, /* xConnect - connect to an existing table */ + expertBestIndex, /* xBestIndex - Determine search strategy */ + expertDisconnect, /* xDisconnect - Disconnect from a table */ + expertDisconnect, /* xDestroy - Drop a table */ + expertOpen, /* xOpen - open a cursor */ + expertClose, /* xClose - close a cursor */ + expertFilter, /* xFilter - configure scan constraints */ + expertNext, /* xNext - advance a cursor */ + expertEof, /* xEof */ + expertColumn, /* xColumn - read data */ + expertRowid, /* xRowid - read data */ + expertUpdate, /* xUpdate - write data */ + 0, /* xBegin - begin transaction */ + 0, /* xSync - sync transaction */ + 0, /* xCommit - commit transaction */ + 0, /* xRollback - rollback transaction */ + 0, /* xFindFunction - function overloading */ + 0, /* xRename - rename the table */ + 0, /* xSavepoint */ + 0, /* xRelease */ + 0, /* xRollbackTo */ + 0, /* xShadowName */ + }; + + return sqlite3_create_module(p->dbv, "expert", &expertModule, (void*)p); } /* ** End of virtual table implementation. @@ -9919,8 +9919,8 @@ static int idxRegisterVtab(sqlite3expert *p){ ** returning. Otherwise, discard the sqlite3_finalize() return value. */ static void idxFinalize(int *pRc, sqlite3_stmt *pStmt){ - int rc = sqlite3_finalize(pStmt); - if( *pRc==SQLITE_OK ) *pRc = rc; + int rc = sqlite3_finalize(pStmt); + if( *pRc==SQLITE_OK ) *pRc = rc; } /* @@ -9934,85 +9934,85 @@ static void idxFinalize(int *pRc, sqlite3_stmt *pStmt){ ** IdxTable object or error message using sqlite3_free(). */ static int idxGetTableInfo( - sqlite3 *db, /* Database connection to read details from */ - const char *zTab, /* Table name */ - IdxTable **ppOut, /* OUT: New object (if successful) */ - char **pzErrmsg /* OUT: Error message (if not) */ + sqlite3 *db, /* Database connection to read details from */ + const char *zTab, /* Table name */ + IdxTable **ppOut, /* OUT: New object (if successful) */ + char **pzErrmsg /* OUT: Error message (if not) */ ){ - sqlite3_stmt *p1 = 0; - int nCol = 0; - int nTab = STRLEN(zTab); - int nByte = sizeof(IdxTable) + nTab + 1; - IdxTable *pNew = 0; - int rc, rc2; - char *pCsr = 0; - int nPk = 0; - - rc = idxPrintfPrepareStmt(db, &p1, pzErrmsg, "PRAGMA table_xinfo=%Q", zTab); - while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(p1) ){ - const char *zCol = (const char*)sqlite3_column_text(p1, 1); - const char *zColSeq = 0; - nByte += 1 + STRLEN(zCol); - rc = sqlite3_table_column_metadata( - db, "main", zTab, zCol, 0, &zColSeq, 0, 0, 0 - ); - if( zColSeq==0 ) zColSeq = "binary"; - nByte += 1 + STRLEN(zColSeq); - nCol++; - nPk += (sqlite3_column_int(p1, 5)>0); - } - rc2 = sqlite3_reset(p1); - if( rc==SQLITE_OK ) rc = rc2; + sqlite3_stmt *p1 = 0; + int nCol = 0; + int nTab = STRLEN(zTab); + int nByte = sizeof(IdxTable) + nTab + 1; + IdxTable *pNew = 0; + int rc, rc2; + char *pCsr = 0; + int nPk = 0; + + rc = idxPrintfPrepareStmt(db, &p1, pzErrmsg, "PRAGMA table_xinfo=%Q", zTab); + while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(p1) ){ + const char *zCol = (const char*)sqlite3_column_text(p1, 1); + const char *zColSeq = 0; + nByte += 1 + STRLEN(zCol); + rc = sqlite3_table_column_metadata( + db, "main", zTab, zCol, 0, &zColSeq, 0, 0, 0 + ); + if( zColSeq==0 ) zColSeq = "binary"; + nByte += 1 + STRLEN(zColSeq); + nCol++; + nPk += (sqlite3_column_int(p1, 5)>0); + } + rc2 = sqlite3_reset(p1); + if( rc==SQLITE_OK ) rc = rc2; + + nByte += sizeof(IdxColumn) * nCol; + if( rc==SQLITE_OK ){ + pNew = idxMalloc(&rc, nByte); + } + if( rc==SQLITE_OK ){ + pNew->aCol = (IdxColumn*)&pNew[1]; + pNew->nCol = nCol; + pCsr = (char*)&pNew->aCol[nCol]; + } + + nCol = 0; + while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(p1) ){ + const char *zCol = (const char*)sqlite3_column_text(p1, 1); + const char *zColSeq = 0; + int nCopy = STRLEN(zCol) + 1; + pNew->aCol[nCol].zName = pCsr; + pNew->aCol[nCol].iPk = (sqlite3_column_int(p1, 5)==1 && nPk==1); + memcpy(pCsr, zCol, nCopy); + pCsr += nCopy; - nByte += sizeof(IdxColumn) * nCol; + rc = sqlite3_table_column_metadata( + db, "main", zTab, zCol, 0, &zColSeq, 0, 0, 0 + ); if( rc==SQLITE_OK ){ - pNew = idxMalloc(&rc, nByte); + if( zColSeq==0 ) zColSeq = "binary"; + nCopy = STRLEN(zColSeq) + 1; + pNew->aCol[nCol].zColl = pCsr; + memcpy(pCsr, zColSeq, nCopy); + pCsr += nCopy; } - if( rc==SQLITE_OK ){ - pNew->aCol = (IdxColumn*)&pNew[1]; - pNew->nCol = nCol; - pCsr = (char*)&pNew->aCol[nCol]; - } - - nCol = 0; - while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(p1) ){ - const char *zCol = (const char*)sqlite3_column_text(p1, 1); - const char *zColSeq = 0; - int nCopy = STRLEN(zCol) + 1; - pNew->aCol[nCol].zName = pCsr; - pNew->aCol[nCol].iPk = (sqlite3_column_int(p1, 5)==1 && nPk==1); - memcpy(pCsr, zCol, nCopy); - pCsr += nCopy; - - rc = sqlite3_table_column_metadata( - db, "main", zTab, zCol, 0, &zColSeq, 0, 0, 0 - ); - if( rc==SQLITE_OK ){ - if( zColSeq==0 ) zColSeq = "binary"; - nCopy = STRLEN(zColSeq) + 1; - pNew->aCol[nCol].zColl = pCsr; - memcpy(pCsr, zColSeq, nCopy); - pCsr += nCopy; - } - nCol++; - } - idxFinalize(&rc, p1); + nCol++; + } + idxFinalize(&rc, p1); - if( rc!=SQLITE_OK ){ - sqlite3_free(pNew); - pNew = 0; - }else if( ALWAYS(pNew!=0) ){ - pNew->zName = pCsr; - if( ALWAYS(pNew->zName!=0) ) memcpy(pNew->zName, zTab, nTab+1); - } + if( rc!=SQLITE_OK ){ + sqlite3_free(pNew); + pNew = 0; + }else if( ALWAYS(pNew!=0) ){ + pNew->zName = pCsr; + if( ALWAYS(pNew->zName!=0) ) memcpy(pNew->zName, zTab, nTab+1); + } - *ppOut = pNew; - return rc; + *ppOut = pNew; + return rc; } /* -** This function is a no-op if *pRc is set to anything other than +** This function is a no-op if *pRc is set to anything other than ** SQLITE_OK when it is called. ** ** If *pRc is initially set to SQLITE_OK, then the text specified by @@ -10021,31 +10021,31 @@ static int idxGetTableInfo( ** zIn before returning. */ static char *idxAppendText(int *pRc, char *zIn, const char *zFmt, ...){ - va_list ap; - char *zAppend = 0; - char *zRet = 0; - int nIn = zIn ? STRLEN(zIn) : 0; - int nAppend = 0; - va_start(ap, zFmt); - if( *pRc==SQLITE_OK ){ - zAppend = sqlite3_vmprintf(zFmt, ap); - if( zAppend ){ - nAppend = STRLEN(zAppend); - zRet = (char*)sqlite3_malloc(nIn + nAppend + 1); - } - if( zAppend && zRet ){ - if( nIn ) memcpy(zRet, zIn, nIn); - memcpy(&zRet[nIn], zAppend, nAppend+1); - }else{ - sqlite3_free(zRet); - zRet = 0; - *pRc = SQLITE_NOMEM; - } - sqlite3_free(zAppend); - sqlite3_free(zIn); + va_list ap; + char *zAppend = 0; + char *zRet = 0; + int nIn = zIn ? STRLEN(zIn) : 0; + int nAppend = 0; + va_start(ap, zFmt); + if( *pRc==SQLITE_OK ){ + zAppend = sqlite3_vmprintf(zFmt, ap); + if( zAppend ){ + nAppend = STRLEN(zAppend); + zRet = (char*)sqlite3_malloc(nIn + nAppend + 1); + } + if( zAppend && zRet ){ + if( nIn ) memcpy(zRet, zIn, nIn); + memcpy(&zRet[nIn], zAppend, nAppend+1); + }else{ + sqlite3_free(zRet); + zRet = 0; + *pRc = SQLITE_NOMEM; } - va_end(ap); - return zRet; + sqlite3_free(zAppend); + sqlite3_free(zIn); + } + va_end(ap); + return zRet; } /* @@ -10053,17 +10053,17 @@ static char *idxAppendText(int *pRc, char *zIn, const char *zFmt, ...){ ** identifier, or false otherwise. */ static int idxIdentifierRequiresQuotes(const char *zId){ - int i; - for(i=0; zId[i]; i++){ - if( !(zId[i]=='_') - && !(zId[i]>='0' && zId[i]<='9') - && !(zId[i]>='a' && zId[i]<='z') - && !(zId[i]>='A' && zId[i]<='Z') - ){ - return 1; - } + int i; + for(i=0; zId[i]; i++){ + if( !(zId[i]=='_') + && !(zId[i]>='0' && zId[i]<='9') + && !(zId[i]>='a' && zId[i]<='z') + && !(zId[i]>='A' && zId[i]<='Z') + ){ + return 1; } - return 0; + } + return 0; } /* @@ -10071,108 +10071,108 @@ static int idxIdentifierRequiresQuotes(const char *zId){ ** pCons to the string passed as zIn and returns the result. */ static char *idxAppendColDefn( - int *pRc, /* IN/OUT: Error code */ - char *zIn, /* Column defn accumulated so far */ - IdxTable *pTab, /* Table index will be created on */ - IdxConstraint *pCons + int *pRc, /* IN/OUT: Error code */ + char *zIn, /* Column defn accumulated so far */ + IdxTable *pTab, /* Table index will be created on */ + IdxConstraint *pCons ){ - char *zRet = zIn; - IdxColumn *p = &pTab->aCol[pCons->iCol]; - if( zRet ) zRet = idxAppendText(pRc, zRet, ", "); - - if( idxIdentifierRequiresQuotes(p->zName) ){ - zRet = idxAppendText(pRc, zRet, "%Q", p->zName); + char *zRet = zIn; + IdxColumn *p = &pTab->aCol[pCons->iCol]; + if( zRet ) zRet = idxAppendText(pRc, zRet, ", "); + + if( idxIdentifierRequiresQuotes(p->zName) ){ + zRet = idxAppendText(pRc, zRet, "%Q", p->zName); + }else{ + zRet = idxAppendText(pRc, zRet, "%s", p->zName); + } + + if( sqlite3_stricmp(p->zColl, pCons->zColl) ){ + if( idxIdentifierRequiresQuotes(pCons->zColl) ){ + zRet = idxAppendText(pRc, zRet, " COLLATE %Q", pCons->zColl); }else{ - zRet = idxAppendText(pRc, zRet, "%s", p->zName); - } - - if( sqlite3_stricmp(p->zColl, pCons->zColl) ){ - if( idxIdentifierRequiresQuotes(pCons->zColl) ){ - zRet = idxAppendText(pRc, zRet, " COLLATE %Q", pCons->zColl); - }else{ - zRet = idxAppendText(pRc, zRet, " COLLATE %s", pCons->zColl); - } + zRet = idxAppendText(pRc, zRet, " COLLATE %s", pCons->zColl); } + } - if( pCons->bDesc ){ - zRet = idxAppendText(pRc, zRet, " DESC"); - } - return zRet; + if( pCons->bDesc ){ + zRet = idxAppendText(pRc, zRet, " DESC"); + } + return zRet; } /* ** Search database dbm for an index compatible with the one idxCreateFromCons() -** would create from arguments pScan, pEq and pTail. If no error occurs and +** would create from arguments pScan, pEq and pTail. If no error occurs and ** such an index is found, return non-zero. Or, if no such index is found, ** return zero. ** ** If an error occurs, set *pRc to an SQLite error code and return zero. */ static int idxFindCompatible( - int *pRc, /* OUT: Error code */ - sqlite3* dbm, /* Database to search */ - IdxScan *pScan, /* Scan for table to search for index on */ - IdxConstraint *pEq, /* List of == constraints */ - IdxConstraint *pTail /* List of range constraints */ + int *pRc, /* OUT: Error code */ + sqlite3* dbm, /* Database to search */ + IdxScan *pScan, /* Scan for table to search for index on */ + IdxConstraint *pEq, /* List of == constraints */ + IdxConstraint *pTail /* List of range constraints */ ){ - const char *zTbl = pScan->pTab->zName; - sqlite3_stmt *pIdxList = 0; - IdxConstraint *pIter; - int nEq = 0; /* Number of elements in pEq */ - int rc; - - /* Count the elements in list pEq */ - for(pIter=pEq; pIter; pIter=pIter->pLink) nEq++; - - rc = idxPrintfPrepareStmt(dbm, &pIdxList, 0, "PRAGMA index_list=%Q", zTbl); - while( rc==SQLITE_OK && sqlite3_step(pIdxList)==SQLITE_ROW ){ - int bMatch = 1; - IdxConstraint *pT = pTail; - sqlite3_stmt *pInfo = 0; - const char *zIdx = (const char*)sqlite3_column_text(pIdxList, 1); - - /* Zero the IdxConstraint.bFlag values in the pEq list */ - for(pIter=pEq; pIter; pIter=pIter->pLink) pIter->bFlag = 0; - - rc = idxPrintfPrepareStmt(dbm, &pInfo, 0, "PRAGMA index_xInfo=%Q", zIdx); - while( rc==SQLITE_OK && sqlite3_step(pInfo)==SQLITE_ROW ){ - int iIdx = sqlite3_column_int(pInfo, 0); - int iCol = sqlite3_column_int(pInfo, 1); - const char *zColl = (const char*)sqlite3_column_text(pInfo, 4); - - if( iIdxpLink){ - if( pIter->bFlag ) continue; - if( pIter->iCol!=iCol ) continue; - if( sqlite3_stricmp(pIter->zColl, zColl) ) continue; - pIter->bFlag = 1; - break; - } - if( pIter==0 ){ - bMatch = 0; - break; - } - }else{ - if( pT ){ - if( pT->iCol!=iCol || sqlite3_stricmp(pT->zColl, zColl) ){ - bMatch = 0; - break; - } - pT = pT->pLink; - } - } + const char *zTbl = pScan->pTab->zName; + sqlite3_stmt *pIdxList = 0; + IdxConstraint *pIter; + int nEq = 0; /* Number of elements in pEq */ + int rc; + + /* Count the elements in list pEq */ + for(pIter=pEq; pIter; pIter=pIter->pLink) nEq++; + + rc = idxPrintfPrepareStmt(dbm, &pIdxList, 0, "PRAGMA index_list=%Q", zTbl); + while( rc==SQLITE_OK && sqlite3_step(pIdxList)==SQLITE_ROW ){ + int bMatch = 1; + IdxConstraint *pT = pTail; + sqlite3_stmt *pInfo = 0; + const char *zIdx = (const char*)sqlite3_column_text(pIdxList, 1); + + /* Zero the IdxConstraint.bFlag values in the pEq list */ + for(pIter=pEq; pIter; pIter=pIter->pLink) pIter->bFlag = 0; + + rc = idxPrintfPrepareStmt(dbm, &pInfo, 0, "PRAGMA index_xInfo=%Q", zIdx); + while( rc==SQLITE_OK && sqlite3_step(pInfo)==SQLITE_ROW ){ + int iIdx = sqlite3_column_int(pInfo, 0); + int iCol = sqlite3_column_int(pInfo, 1); + const char *zColl = (const char*)sqlite3_column_text(pInfo, 4); + + if( iIdxpLink){ + if( pIter->bFlag ) continue; + if( pIter->iCol!=iCol ) continue; + if( sqlite3_stricmp(pIter->zColl, zColl) ) continue; + pIter->bFlag = 1; + break; + } + if( pIter==0 ){ + bMatch = 0; + break; + } + }else{ + if( pT ){ + if( pT->iCol!=iCol || sqlite3_stricmp(pT->zColl, zColl) ){ + bMatch = 0; + break; + } + pT = pT->pLink; } - idxFinalize(&rc, pInfo); + } + } + idxFinalize(&rc, pInfo); - if( rc==SQLITE_OK && bMatch ){ - sqlite3_finalize(pIdxList); - return 1; - } + if( rc==SQLITE_OK && bMatch ){ + sqlite3_finalize(pIdxList); + return 1; } - idxFinalize(&rc, pIdxList); + } + idxFinalize(&rc, pIdxList); - *pRc = rc; - return 0; + *pRc = rc; + return 0; } /* Callback for sqlite3_exec() with query with leading count(*) column. @@ -10180,96 +10180,96 @@ static int idxFindCompatible( * if that leading column is not exactly '0'. */ static int countNonzeros(void* pCount, int nc, - char* azResults[], char* azColumns[]){ - (void)azColumns; /* Suppress unused parameter warning */ - if( nc>0 && (azResults[0][0]!='0' || azResults[0][1]!=0) ){ - *((int *)pCount) += 1; - } - return 0; + char* azResults[], char* azColumns[]){ + (void)azColumns; /* Suppress unused parameter warning */ + if( nc>0 && (azResults[0][0]!='0' || azResults[0][1]!=0) ){ + *((int *)pCount) += 1; + } + return 0; } static int idxCreateFromCons( - sqlite3expert *p, - IdxScan *pScan, - IdxConstraint *pEq, - IdxConstraint *pTail + sqlite3expert *p, + IdxScan *pScan, + IdxConstraint *pEq, + IdxConstraint *pTail ){ - sqlite3 *dbm = p->dbm; - int rc = SQLITE_OK; - if( (pEq || pTail) && 0==idxFindCompatible(&rc, dbm, pScan, pEq, pTail) ){ - IdxTable *pTab = pScan->pTab; - char *zCols = 0; - char *zIdx = 0; - IdxConstraint *pCons; - unsigned int h = 0; - const char *zFmt; - - for(pCons=pEq; pCons; pCons=pCons->pLink){ - zCols = idxAppendColDefn(&rc, zCols, pTab, pCons); - } - for(pCons=pTail; pCons; pCons=pCons->pLink){ - zCols = idxAppendColDefn(&rc, zCols, pTab, pCons); - } + sqlite3 *dbm = p->dbm; + int rc = SQLITE_OK; + if( (pEq || pTail) && 0==idxFindCompatible(&rc, dbm, pScan, pEq, pTail) ){ + IdxTable *pTab = pScan->pTab; + char *zCols = 0; + char *zIdx = 0; + IdxConstraint *pCons; + unsigned int h = 0; + const char *zFmt; - if( rc==SQLITE_OK ){ - /* Hash the list of columns to come up with a name for the index */ - const char *zTable = pScan->pTab->zName; - int quoteTable = idxIdentifierRequiresQuotes(zTable); - char *zName = 0; /* Index name */ - int collisions = 0; - do{ - int i; - char *zFind; - for(i=0; zCols[i]; i++){ - h += ((h<<3) + zCols[i]); - } - sqlite3_free(zName); - zName = sqlite3_mprintf("%s_idx_%08x", zTable, h); - if( zName==0 ) break; - /* Is is unique among table, view and index names? */ - zFmt = "SELECT count(*) FROM sqlite_schema WHERE name=%Q" - " AND type in ('index','table','view')"; - zFind = sqlite3_mprintf(zFmt, zName); - i = 0; - rc = sqlite3_exec(dbm, zFind, countNonzeros, &i, 0); - assert(rc==SQLITE_OK); - sqlite3_free(zFind); - if( i==0 ){ - collisions = 0; - break; - } - ++collisions; - }while( collisions<50 && zName!=0 ); - if( collisions ){ - /* This return means "Gave up trying to find a unique index name." */ - rc = SQLITE_BUSY_TIMEOUT; - }else if( zName==0 ){ - rc = SQLITE_NOMEM; - }else{ - if( quoteTable ){ - zFmt = "CREATE INDEX \"%w\" ON \"%w\"(%s)"; - }else{ - zFmt = "CREATE INDEX %s ON %s(%s)"; - } - zIdx = sqlite3_mprintf(zFmt, zName, zTable, zCols); - if( !zIdx ){ - rc = SQLITE_NOMEM; - }else{ - rc = sqlite3_exec(dbm, zIdx, 0, 0, p->pzErrmsg); - if( rc!=SQLITE_OK ){ - rc = SQLITE_BUSY_TIMEOUT; - }else{ - idxHashAdd(&rc, &p->hIdx, zName, zIdx); - } - } - sqlite3_free(zName); - sqlite3_free(zIdx); - } - } + for(pCons=pEq; pCons; pCons=pCons->pLink){ + zCols = idxAppendColDefn(&rc, zCols, pTab, pCons); + } + for(pCons=pTail; pCons; pCons=pCons->pLink){ + zCols = idxAppendColDefn(&rc, zCols, pTab, pCons); + } - sqlite3_free(zCols); + if( rc==SQLITE_OK ){ + /* Hash the list of columns to come up with a name for the index */ + const char *zTable = pScan->pTab->zName; + int quoteTable = idxIdentifierRequiresQuotes(zTable); + char *zName = 0; /* Index name */ + int collisions = 0; + do{ + int i; + char *zFind; + for(i=0; zCols[i]; i++){ + h += ((h<<3) + zCols[i]); + } + sqlite3_free(zName); + zName = sqlite3_mprintf("%s_idx_%08x", zTable, h); + if( zName==0 ) break; + /* Is is unique among table, view and index names? */ + zFmt = "SELECT count(*) FROM sqlite_schema WHERE name=%Q" + " AND type in ('index','table','view')"; + zFind = sqlite3_mprintf(zFmt, zName); + i = 0; + rc = sqlite3_exec(dbm, zFind, countNonzeros, &i, 0); + assert(rc==SQLITE_OK); + sqlite3_free(zFind); + if( i==0 ){ + collisions = 0; + break; + } + ++collisions; + }while( collisions<50 && zName!=0 ); + if( collisions ){ + /* This return means "Gave up trying to find a unique index name." */ + rc = SQLITE_BUSY_TIMEOUT; + }else if( zName==0 ){ + rc = SQLITE_NOMEM; + }else{ + if( quoteTable ){ + zFmt = "CREATE INDEX \"%w\" ON \"%w\"(%s)"; + }else{ + zFmt = "CREATE INDEX %s ON %s(%s)"; + } + zIdx = sqlite3_mprintf(zFmt, zName, zTable, zCols); + if( !zIdx ){ + rc = SQLITE_NOMEM; + }else{ + rc = sqlite3_exec(dbm, zIdx, 0, 0, p->pzErrmsg); + if( rc!=SQLITE_OK ){ + rc = SQLITE_BUSY_TIMEOUT; + }else{ + idxHashAdd(&rc, &p->hIdx, zName, zIdx); + } + } + sqlite3_free(zName); + sqlite3_free(zIdx); + } } - return rc; + + sqlite3_free(zCols); + } + return rc; } /* @@ -10277,77 +10277,77 @@ static int idxCreateFromCons( ** a constraint compatible with *p. Otherwise return false. */ static int idxFindConstraint(IdxConstraint *pList, IdxConstraint *p){ - IdxConstraint *pCmp; - for(pCmp=pList; pCmp; pCmp=pCmp->pLink){ - if( p->iCol==pCmp->iCol ) return 1; - } - return 0; + IdxConstraint *pCmp; + for(pCmp=pList; pCmp; pCmp=pCmp->pLink){ + if( p->iCol==pCmp->iCol ) return 1; + } + return 0; } static int idxCreateFromWhere( - sqlite3expert *p, - IdxScan *pScan, /* Create indexes for this scan */ - IdxConstraint *pTail /* range/ORDER BY constraints for inclusion */ + sqlite3expert *p, + IdxScan *pScan, /* Create indexes for this scan */ + IdxConstraint *pTail /* range/ORDER BY constraints for inclusion */ ){ - IdxConstraint *p1 = 0; - IdxConstraint *pCon; - int rc; + IdxConstraint *p1 = 0; + IdxConstraint *pCon; + int rc; - /* Gather up all the == constraints. */ - for(pCon=pScan->pEq; pCon; pCon=pCon->pNext){ - if( !idxFindConstraint(p1, pCon) && !idxFindConstraint(pTail, pCon) ){ - pCon->pLink = p1; - p1 = pCon; - } + /* Gather up all the == constraints. */ + for(pCon=pScan->pEq; pCon; pCon=pCon->pNext){ + if( !idxFindConstraint(p1, pCon) && !idxFindConstraint(pTail, pCon) ){ + pCon->pLink = p1; + p1 = pCon; } + } - /* Create an index using the == constraints collected above. And the + /* Create an index using the == constraints collected above. And the ** range constraint/ORDER BY terms passed in by the caller, if any. */ - rc = idxCreateFromCons(p, pScan, p1, pTail); + rc = idxCreateFromCons(p, pScan, p1, pTail); - /* If no range/ORDER BY passed by the caller, create a version of the + /* If no range/ORDER BY passed by the caller, create a version of the ** index for each range constraint. */ - if( pTail==0 ){ - for(pCon=pScan->pRange; rc==SQLITE_OK && pCon; pCon=pCon->pNext){ - assert( pCon->pLink==0 ); - if( !idxFindConstraint(p1, pCon) && !idxFindConstraint(pTail, pCon) ){ - rc = idxCreateFromCons(p, pScan, p1, pCon); - } - } + if( pTail==0 ){ + for(pCon=pScan->pRange; rc==SQLITE_OK && pCon; pCon=pCon->pNext){ + assert( pCon->pLink==0 ); + if( !idxFindConstraint(p1, pCon) && !idxFindConstraint(pTail, pCon) ){ + rc = idxCreateFromCons(p, pScan, p1, pCon); + } } + } - return rc; + return rc; } /* -** Create candidate indexes in database [dbm] based on the data in +** Create candidate indexes in database [dbm] based on the data in ** linked-list pScan. */ static int idxCreateCandidates(sqlite3expert *p){ - int rc = SQLITE_OK; - IdxScan *pIter; + int rc = SQLITE_OK; + IdxScan *pIter; - for(pIter=p->pScan; pIter && rc==SQLITE_OK; pIter=pIter->pNextScan){ - rc = idxCreateFromWhere(p, pIter, 0); - if( rc==SQLITE_OK && pIter->pOrder ){ - rc = idxCreateFromWhere(p, pIter, pIter->pOrder); - } + for(pIter=p->pScan; pIter && rc==SQLITE_OK; pIter=pIter->pNextScan){ + rc = idxCreateFromWhere(p, pIter, 0); + if( rc==SQLITE_OK && pIter->pOrder ){ + rc = idxCreateFromWhere(p, pIter, pIter->pOrder); } + } - return rc; + return rc; } /* ** Free all elements of the linked list starting at pConstraint. */ static void idxConstraintFree(IdxConstraint *pConstraint){ - IdxConstraint *pNext; - IdxConstraint *p; + IdxConstraint *pNext; + IdxConstraint *p; - for(p=pConstraint; p; p=pNext){ - pNext = p->pNext; - sqlite3_free(p); - } + for(p=pConstraint; p; p=pNext){ + pNext = p->pNext; + sqlite3_free(p); + } } /* @@ -10355,54 +10355,54 @@ static void idxConstraintFree(IdxConstraint *pConstraint){ ** (pLast is not freed). */ static void idxScanFree(IdxScan *pScan, IdxScan *pLast){ - IdxScan *p; - IdxScan *pNext; - for(p=pScan; p!=pLast; p=pNext){ - pNext = p->pNextScan; - idxConstraintFree(p->pOrder); - idxConstraintFree(p->pEq); - idxConstraintFree(p->pRange); - sqlite3_free(p); - } + IdxScan *p; + IdxScan *pNext; + for(p=pScan; p!=pLast; p=pNext){ + pNext = p->pNextScan; + idxConstraintFree(p->pOrder); + idxConstraintFree(p->pEq); + idxConstraintFree(p->pRange); + sqlite3_free(p); + } } /* -** Free all elements of the linked list starting from pStatement up +** Free all elements of the linked list starting from pStatement up ** until pLast (pLast is not freed). */ static void idxStatementFree(IdxStatement *pStatement, IdxStatement *pLast){ - IdxStatement *p; - IdxStatement *pNext; - for(p=pStatement; p!=pLast; p=pNext){ - pNext = p->pNext; - sqlite3_free(p->zEQP); - sqlite3_free(p->zIdx); - sqlite3_free(p); - } + IdxStatement *p; + IdxStatement *pNext; + for(p=pStatement; p!=pLast; p=pNext){ + pNext = p->pNext; + sqlite3_free(p->zEQP); + sqlite3_free(p->zIdx); + sqlite3_free(p); + } } /* ** Free the linked list of IdxTable objects starting at pTab. */ static void idxTableFree(IdxTable *pTab){ - IdxTable *pIter; - IdxTable *pNext; - for(pIter=pTab; pIter; pIter=pNext){ - pNext = pIter->pNext; - sqlite3_free(pIter); - } + IdxTable *pIter; + IdxTable *pNext; + for(pIter=pTab; pIter; pIter=pNext){ + pNext = pIter->pNext; + sqlite3_free(pIter); + } } /* ** Free the linked list of IdxWrite objects starting at pTab. */ static void idxWriteFree(IdxWrite *pTab){ - IdxWrite *pIter; - IdxWrite *pNext; - for(pIter=pTab; pIter; pIter=pNext){ - pNext = pIter->pNext; - sqlite3_free(pIter); - } + IdxWrite *pIter; + IdxWrite *pNext; + for(pIter=pTab; pIter; pIter=pNext){ + pNext = pIter->pNext; + sqlite3_free(pIter); + } } @@ -10413,529 +10413,529 @@ static void idxWriteFree(IdxWrite *pTab){ ** IdxStatement.zIdx and IdxStatement.zEQP with the results. */ int idxFindIndexes( - sqlite3expert *p, - char **pzErr /* OUT: Error message (sqlite3_malloc) */ + sqlite3expert *p, + char **pzErr /* OUT: Error message (sqlite3_malloc) */ ){ - IdxStatement *pStmt; - sqlite3 *dbm = p->dbm; - int rc = SQLITE_OK; - - IdxHash hIdx; - idxHashInit(&hIdx); - - for(pStmt=p->pStatement; rc==SQLITE_OK && pStmt; pStmt=pStmt->pNext){ - IdxHashEntry *pEntry; - sqlite3_stmt *pExplain = 0; - idxHashClear(&hIdx); - rc = idxPrintfPrepareStmt(dbm, &pExplain, pzErr, - "EXPLAIN QUERY PLAN %s", pStmt->zSql - ); - while( rc==SQLITE_OK && sqlite3_step(pExplain)==SQLITE_ROW ){ - /* int iId = sqlite3_column_int(pExplain, 0); */ - /* int iParent = sqlite3_column_int(pExplain, 1); */ - /* int iNotUsed = sqlite3_column_int(pExplain, 2); */ - const char *zDetail = (const char*)sqlite3_column_text(pExplain, 3); - int nDetail; - int i; - - if( !zDetail ) continue; - nDetail = STRLEN(zDetail); - - for(i=0; ihIdx, zIdx, nIdx); - if( zSql ){ - idxHashAdd(&rc, &hIdx, zSql, 0); - if( rc ) goto find_indexes_out; - } - break; - } - } + IdxStatement *pStmt; + sqlite3 *dbm = p->dbm; + int rc = SQLITE_OK; - if( zDetail[0]!='-' ){ - pStmt->zEQP = idxAppendText(&rc, pStmt->zEQP, "%s\n", zDetail); - } - } + IdxHash hIdx; + idxHashInit(&hIdx); - for(pEntry=hIdx.pFirst; pEntry; pEntry=pEntry->pNext){ - pStmt->zIdx = idxAppendText(&rc, pStmt->zIdx, "%s;\n", pEntry->zKey); + for(pStmt=p->pStatement; rc==SQLITE_OK && pStmt; pStmt=pStmt->pNext){ + IdxHashEntry *pEntry; + sqlite3_stmt *pExplain = 0; + idxHashClear(&hIdx); + rc = idxPrintfPrepareStmt(dbm, &pExplain, pzErr, + "EXPLAIN QUERY PLAN %s", pStmt->zSql + ); + while( rc==SQLITE_OK && sqlite3_step(pExplain)==SQLITE_ROW ){ + /* int iId = sqlite3_column_int(pExplain, 0); */ + /* int iParent = sqlite3_column_int(pExplain, 1); */ + /* int iNotUsed = sqlite3_column_int(pExplain, 2); */ + const char *zDetail = (const char*)sqlite3_column_text(pExplain, 3); + int nDetail; + int i; + + if( !zDetail ) continue; + nDetail = STRLEN(zDetail); + + for(i=0; ihIdx, zIdx, nIdx); + if( zSql ){ + idxHashAdd(&rc, &hIdx, zSql, 0); + if( rc ) goto find_indexes_out; + } + break; } + } - idxFinalize(&rc, pExplain); + if( zDetail[0]!='-' ){ + pStmt->zEQP = idxAppendText(&rc, pStmt->zEQP, "%s\n", zDetail); + } } -find_indexes_out: - idxHashClear(&hIdx); - return rc; + for(pEntry=hIdx.pFirst; pEntry; pEntry=pEntry->pNext){ + pStmt->zIdx = idxAppendText(&rc, pStmt->zIdx, "%s;\n", pEntry->zKey); + } + + idxFinalize(&rc, pExplain); + } + + find_indexes_out: + idxHashClear(&hIdx); + return rc; } static int idxAuthCallback( - void *pCtx, - int eOp, - const char *z3, - const char *z4, - const char *zDb, - const char *zTrigger + void *pCtx, + int eOp, + const char *z3, + const char *z4, + const char *zDb, + const char *zTrigger ){ - int rc = SQLITE_OK; - (void)z4; - (void)zTrigger; - if( eOp==SQLITE_INSERT || eOp==SQLITE_UPDATE || eOp==SQLITE_DELETE ){ - if( sqlite3_stricmp(zDb, "main")==0 ){ - sqlite3expert *p = (sqlite3expert*)pCtx; - IdxTable *pTab; - for(pTab=p->pTable; pTab; pTab=pTab->pNext){ - if( 0==sqlite3_stricmp(z3, pTab->zName) ) break; - } - if( pTab ){ - IdxWrite *pWrite; - for(pWrite=p->pWrite; pWrite; pWrite=pWrite->pNext){ - if( pWrite->pTab==pTab && pWrite->eOp==eOp ) break; - } - if( pWrite==0 ){ - pWrite = idxMalloc(&rc, sizeof(IdxWrite)); - if( rc==SQLITE_OK ){ - pWrite->pTab = pTab; - pWrite->eOp = eOp; - pWrite->pNext = p->pWrite; - p->pWrite = pWrite; - } - } - } - } - } - return rc; + int rc = SQLITE_OK; + (void)z4; + (void)zTrigger; + if( eOp==SQLITE_INSERT || eOp==SQLITE_UPDATE || eOp==SQLITE_DELETE ){ + if( sqlite3_stricmp(zDb, "main")==0 ){ + sqlite3expert *p = (sqlite3expert*)pCtx; + IdxTable *pTab; + for(pTab=p->pTable; pTab; pTab=pTab->pNext){ + if( 0==sqlite3_stricmp(z3, pTab->zName) ) break; + } + if( pTab ){ + IdxWrite *pWrite; + for(pWrite=p->pWrite; pWrite; pWrite=pWrite->pNext){ + if( pWrite->pTab==pTab && pWrite->eOp==eOp ) break; + } + if( pWrite==0 ){ + pWrite = idxMalloc(&rc, sizeof(IdxWrite)); + if( rc==SQLITE_OK ){ + pWrite->pTab = pTab; + pWrite->eOp = eOp; + pWrite->pNext = p->pWrite; + p->pWrite = pWrite; + } + } + } + } + } + return rc; } static int idxProcessOneTrigger( - sqlite3expert *p, - IdxWrite *pWrite, - char **pzErr + sqlite3expert *p, + IdxWrite *pWrite, + char **pzErr ){ - static const char *zInt = UNIQUE_TABLE_NAME; - static const char *zDrop = "DROP TABLE " UNIQUE_TABLE_NAME; - IdxTable *pTab = pWrite->pTab; - const char *zTab = pTab->zName; - const char *zSql = - "SELECT 'CREATE TEMP' || substr(sql, 7) FROM sqlite_schema " - "WHERE tbl_name = %Q AND type IN ('table', 'trigger') " - "ORDER BY type;"; - sqlite3_stmt *pSelect = 0; - int rc = SQLITE_OK; - char *zWrite = 0; - - /* Create the table and its triggers in the temp schema */ - rc = idxPrintfPrepareStmt(p->db, &pSelect, pzErr, zSql, zTab, zTab); - while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSelect) ){ - const char *zCreate = (const char*)sqlite3_column_text(pSelect, 0); - rc = sqlite3_exec(p->dbv, zCreate, 0, 0, pzErr); - } - idxFinalize(&rc, pSelect); - - /* Rename the table in the temp schema to zInt */ - if( rc==SQLITE_OK ){ - char *z = sqlite3_mprintf("ALTER TABLE temp.%Q RENAME TO %Q", zTab, zInt); - if( z==0 ){ - rc = SQLITE_NOMEM; - }else{ - rc = sqlite3_exec(p->dbv, z, 0, 0, pzErr); - sqlite3_free(z); - } - } - - switch( pWrite->eOp ){ - case SQLITE_INSERT: { - int i; - zWrite = idxAppendText(&rc, zWrite, "INSERT INTO %Q VALUES(", zInt); - for(i=0; inCol; i++){ - zWrite = idxAppendText(&rc, zWrite, "%s?", i==0 ? "" : ", "); - } - zWrite = idxAppendText(&rc, zWrite, ")"); - break; - } - case SQLITE_UPDATE: { - int i; - zWrite = idxAppendText(&rc, zWrite, "UPDATE %Q SET ", zInt); - for(i=0; inCol; i++){ - zWrite = idxAppendText(&rc, zWrite, "%s%Q=?", i==0 ? "" : ", ", - pTab->aCol[i].zName - ); - } - break; - } - default: { - assert( pWrite->eOp==SQLITE_DELETE ); - if( rc==SQLITE_OK ){ - zWrite = sqlite3_mprintf("DELETE FROM %Q", zInt); - if( zWrite==0 ) rc = SQLITE_NOMEM; - } - } - } - - if( rc==SQLITE_OK ){ - sqlite3_stmt *pX = 0; - rc = sqlite3_prepare_v2(p->dbv, zWrite, -1, &pX, 0); - idxFinalize(&rc, pX); - if( rc!=SQLITE_OK ){ - idxDatabaseError(p->dbv, pzErr); - } + static const char *zInt = UNIQUE_TABLE_NAME; + static const char *zDrop = "DROP TABLE " UNIQUE_TABLE_NAME; + IdxTable *pTab = pWrite->pTab; + const char *zTab = pTab->zName; + const char *zSql = + "SELECT 'CREATE TEMP' || substr(sql, 7) FROM sqlite_schema " + "WHERE tbl_name = %Q AND type IN ('table', 'trigger') " + "ORDER BY type;"; + sqlite3_stmt *pSelect = 0; + int rc = SQLITE_OK; + char *zWrite = 0; + + /* Create the table and its triggers in the temp schema */ + rc = idxPrintfPrepareStmt(p->db, &pSelect, pzErr, zSql, zTab, zTab); + while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSelect) ){ + const char *zCreate = (const char*)sqlite3_column_text(pSelect, 0); + rc = sqlite3_exec(p->dbv, zCreate, 0, 0, pzErr); + } + idxFinalize(&rc, pSelect); + + /* Rename the table in the temp schema to zInt */ + if( rc==SQLITE_OK ){ + char *z = sqlite3_mprintf("ALTER TABLE temp.%Q RENAME TO %Q", zTab, zInt); + if( z==0 ){ + rc = SQLITE_NOMEM; + }else{ + rc = sqlite3_exec(p->dbv, z, 0, 0, pzErr); + sqlite3_free(z); + } + } + + switch( pWrite->eOp ){ + case SQLITE_INSERT: { + int i; + zWrite = idxAppendText(&rc, zWrite, "INSERT INTO %Q VALUES(", zInt); + for(i=0; inCol; i++){ + zWrite = idxAppendText(&rc, zWrite, "%s?", i==0 ? "" : ", "); + } + zWrite = idxAppendText(&rc, zWrite, ")"); + break; + } + case SQLITE_UPDATE: { + int i; + zWrite = idxAppendText(&rc, zWrite, "UPDATE %Q SET ", zInt); + for(i=0; inCol; i++){ + zWrite = idxAppendText(&rc, zWrite, "%s%Q=?", i==0 ? "" : ", ", + pTab->aCol[i].zName + ); + } + break; + } + default: { + assert( pWrite->eOp==SQLITE_DELETE ); + if( rc==SQLITE_OK ){ + zWrite = sqlite3_mprintf("DELETE FROM %Q", zInt); + if( zWrite==0 ) rc = SQLITE_NOMEM; + } + } + } + + if( rc==SQLITE_OK ){ + sqlite3_stmt *pX = 0; + rc = sqlite3_prepare_v2(p->dbv, zWrite, -1, &pX, 0); + idxFinalize(&rc, pX); + if( rc!=SQLITE_OK ){ + idxDatabaseError(p->dbv, pzErr); } - sqlite3_free(zWrite); + } + sqlite3_free(zWrite); - if( rc==SQLITE_OK ){ - rc = sqlite3_exec(p->dbv, zDrop, 0, 0, pzErr); - } + if( rc==SQLITE_OK ){ + rc = sqlite3_exec(p->dbv, zDrop, 0, 0, pzErr); + } - return rc; + return rc; } static int idxProcessTriggers(sqlite3expert *p, char **pzErr){ - int rc = SQLITE_OK; - IdxWrite *pEnd = 0; - IdxWrite *pFirst = p->pWrite; - - while( rc==SQLITE_OK && pFirst!=pEnd ){ - IdxWrite *pIter; - for(pIter=pFirst; rc==SQLITE_OK && pIter!=pEnd; pIter=pIter->pNext){ - rc = idxProcessOneTrigger(p, pIter, pzErr); - } - pEnd = pFirst; - pFirst = p->pWrite; + int rc = SQLITE_OK; + IdxWrite *pEnd = 0; + IdxWrite *pFirst = p->pWrite; + + while( rc==SQLITE_OK && pFirst!=pEnd ){ + IdxWrite *pIter; + for(pIter=pFirst; rc==SQLITE_OK && pIter!=pEnd; pIter=pIter->pNext){ + rc = idxProcessOneTrigger(p, pIter, pzErr); } + pEnd = pFirst; + pFirst = p->pWrite; + } - return rc; + return rc; } static int idxCreateVtabSchema(sqlite3expert *p, char **pzErrmsg){ - int rc = idxRegisterVtab(p); - sqlite3_stmt *pSchema = 0; + int rc = idxRegisterVtab(p); + sqlite3_stmt *pSchema = 0; - /* For each table in the main db schema: + /* For each table in the main db schema: ** ** 1) Add an entry to the p->pTable list, and ** 2) Create the equivalent virtual table in dbv. */ - rc = idxPrepareStmt(p->db, &pSchema, pzErrmsg, - "SELECT type, name, sql, 1 FROM sqlite_schema " - "WHERE type IN ('table','view') AND name NOT LIKE 'sqlite_%%' " - " UNION ALL " - "SELECT type, name, sql, 2 FROM sqlite_schema " - "WHERE type = 'trigger'" - " AND tbl_name IN(SELECT name FROM sqlite_schema WHERE type = 'view') " - "ORDER BY 4, 1" - ); - while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSchema) ){ - const char *zType = (const char*)sqlite3_column_text(pSchema, 0); - const char *zName = (const char*)sqlite3_column_text(pSchema, 1); - const char *zSql = (const char*)sqlite3_column_text(pSchema, 2); - - if( zType[0]=='v' || zType[1]=='r' ){ - rc = sqlite3_exec(p->dbv, zSql, 0, 0, pzErrmsg); - }else{ - IdxTable *pTab; - rc = idxGetTableInfo(p->db, zName, &pTab, pzErrmsg); - if( rc==SQLITE_OK ){ - int i; - char *zInner = 0; - char *zOuter = 0; - pTab->pNext = p->pTable; - p->pTable = pTab; - - /* The statement the vtab will pass to sqlite3_declare_vtab() */ - zInner = idxAppendText(&rc, 0, "CREATE TABLE x("); - for(i=0; inCol; i++){ - zInner = idxAppendText(&rc, zInner, "%s%Q COLLATE %s", - (i==0 ? "" : ", "), pTab->aCol[i].zName, pTab->aCol[i].zColl - ); - } - zInner = idxAppendText(&rc, zInner, ")"); - - /* The CVT statement to create the vtab */ - zOuter = idxAppendText(&rc, 0, - "CREATE VIRTUAL TABLE %Q USING expert(%Q)", zName, zInner - ); - if( rc==SQLITE_OK ){ - rc = sqlite3_exec(p->dbv, zOuter, 0, 0, pzErrmsg); - } - sqlite3_free(zInner); - sqlite3_free(zOuter); - } + rc = idxPrepareStmt(p->db, &pSchema, pzErrmsg, + "SELECT type, name, sql, 1 FROM sqlite_schema " + "WHERE type IN ('table','view') AND name NOT LIKE 'sqlite_%%' " + " UNION ALL " + "SELECT type, name, sql, 2 FROM sqlite_schema " + "WHERE type = 'trigger'" + " AND tbl_name IN(SELECT name FROM sqlite_schema WHERE type = 'view') " + "ORDER BY 4, 1" + ); + while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSchema) ){ + const char *zType = (const char*)sqlite3_column_text(pSchema, 0); + const char *zName = (const char*)sqlite3_column_text(pSchema, 1); + const char *zSql = (const char*)sqlite3_column_text(pSchema, 2); + + if( zType[0]=='v' || zType[1]=='r' ){ + rc = sqlite3_exec(p->dbv, zSql, 0, 0, pzErrmsg); + }else{ + IdxTable *pTab; + rc = idxGetTableInfo(p->db, zName, &pTab, pzErrmsg); + if( rc==SQLITE_OK ){ + int i; + char *zInner = 0; + char *zOuter = 0; + pTab->pNext = p->pTable; + p->pTable = pTab; + + /* The statement the vtab will pass to sqlite3_declare_vtab() */ + zInner = idxAppendText(&rc, 0, "CREATE TABLE x("); + for(i=0; inCol; i++){ + zInner = idxAppendText(&rc, zInner, "%s%Q COLLATE %s", + (i==0 ? "" : ", "), pTab->aCol[i].zName, pTab->aCol[i].zColl + ); + } + zInner = idxAppendText(&rc, zInner, ")"); + + /* The CVT statement to create the vtab */ + zOuter = idxAppendText(&rc, 0, + "CREATE VIRTUAL TABLE %Q USING expert(%Q)", zName, zInner + ); + if( rc==SQLITE_OK ){ + rc = sqlite3_exec(p->dbv, zOuter, 0, 0, pzErrmsg); } + sqlite3_free(zInner); + sqlite3_free(zOuter); + } } - idxFinalize(&rc, pSchema); - return rc; + } + idxFinalize(&rc, pSchema); + return rc; } struct IdxSampleCtx { - int iTarget; - double target; /* Target nRet/nRow value */ - double nRow; /* Number of rows seen */ - double nRet; /* Number of rows returned */ + int iTarget; + double target; /* Target nRet/nRow value */ + double nRow; /* Number of rows seen */ + double nRet; /* Number of rows returned */ }; static void idxSampleFunc( - sqlite3_context *pCtx, - int argc, - sqlite3_value **argv + sqlite3_context *pCtx, + int argc, + sqlite3_value **argv ){ - struct IdxSampleCtx *p = (struct IdxSampleCtx*)sqlite3_user_data(pCtx); - int bRet; + struct IdxSampleCtx *p = (struct IdxSampleCtx*)sqlite3_user_data(pCtx); + int bRet; - (void)argv; - assert( argc==0 ); - if( p->nRow==0.0 ){ - bRet = 1; - }else{ - bRet = (p->nRet / p->nRow) <= p->target; - if( bRet==0 ){ - unsigned short rnd; - sqlite3_randomness(2, (void*)&rnd); - bRet = ((int)rnd % 100) <= p->iTarget; - } + (void)argv; + assert( argc==0 ); + if( p->nRow==0.0 ){ + bRet = 1; + }else{ + bRet = (p->nRet / p->nRow) <= p->target; + if( bRet==0 ){ + unsigned short rnd; + sqlite3_randomness(2, (void*)&rnd); + bRet = ((int)rnd % 100) <= p->iTarget; } + } - sqlite3_result_int(pCtx, bRet); - p->nRow += 1.0; - p->nRet += (double)bRet; + sqlite3_result_int(pCtx, bRet); + p->nRow += 1.0; + p->nRet += (double)bRet; } struct IdxRemCtx { - int nSlot; - struct IdxRemSlot { - int eType; /* SQLITE_NULL, INTEGER, REAL, TEXT, BLOB */ - i64 iVal; /* SQLITE_INTEGER value */ - double rVal; /* SQLITE_FLOAT value */ - int nByte; /* Bytes of space allocated at z */ - int n; /* Size of buffer z */ - char *z; /* SQLITE_TEXT/BLOB value */ - } aSlot[1]; + int nSlot; + struct IdxRemSlot { + int eType; /* SQLITE_NULL, INTEGER, REAL, TEXT, BLOB */ + i64 iVal; /* SQLITE_INTEGER value */ + double rVal; /* SQLITE_FLOAT value */ + int nByte; /* Bytes of space allocated at z */ + int n; /* Size of buffer z */ + char *z; /* SQLITE_TEXT/BLOB value */ + } aSlot[1]; }; /* ** Implementation of scalar function rem(). */ static void idxRemFunc( - sqlite3_context *pCtx, - int argc, - sqlite3_value **argv + sqlite3_context *pCtx, + int argc, + sqlite3_value **argv ){ - struct IdxRemCtx *p = (struct IdxRemCtx*)sqlite3_user_data(pCtx); - struct IdxRemSlot *pSlot; - int iSlot; - assert( argc==2 ); - - iSlot = sqlite3_value_int(argv[0]); - assert( iSlot<=p->nSlot ); - pSlot = &p->aSlot[iSlot]; - - switch( pSlot->eType ){ - case SQLITE_NULL: - /* no-op */ - break; + struct IdxRemCtx *p = (struct IdxRemCtx*)sqlite3_user_data(pCtx); + struct IdxRemSlot *pSlot; + int iSlot; + assert( argc==2 ); + + iSlot = sqlite3_value_int(argv[0]); + assert( iSlot<=p->nSlot ); + pSlot = &p->aSlot[iSlot]; + + switch( pSlot->eType ){ + case SQLITE_NULL: + /* no-op */ + break; + + case SQLITE_INTEGER: + sqlite3_result_int64(pCtx, pSlot->iVal); + break; + + case SQLITE_FLOAT: + sqlite3_result_double(pCtx, pSlot->rVal); + break; + + case SQLITE_BLOB: + sqlite3_result_blob(pCtx, pSlot->z, pSlot->n, SQLITE_TRANSIENT); + break; + + case SQLITE_TEXT: + sqlite3_result_text(pCtx, pSlot->z, pSlot->n, SQLITE_TRANSIENT); + break; + } + + pSlot->eType = sqlite3_value_type(argv[1]); + switch( pSlot->eType ){ + case SQLITE_NULL: + /* no-op */ + break; + + case SQLITE_INTEGER: + pSlot->iVal = sqlite3_value_int64(argv[1]); + break; + + case SQLITE_FLOAT: + pSlot->rVal = sqlite3_value_double(argv[1]); + break; + + case SQLITE_BLOB: + case SQLITE_TEXT: { + int nByte = sqlite3_value_bytes(argv[1]); + if( nByte>pSlot->nByte ){ + char *zNew = (char*)sqlite3_realloc(pSlot->z, nByte*2); + if( zNew==0 ){ + sqlite3_result_error_nomem(pCtx); + return; + } + pSlot->nByte = nByte*2; + pSlot->z = zNew; + } + pSlot->n = nByte; + if( pSlot->eType==SQLITE_BLOB ){ + memcpy(pSlot->z, sqlite3_value_blob(argv[1]), nByte); + }else{ + memcpy(pSlot->z, sqlite3_value_text(argv[1]), nByte); + } + break; + } + } +} - case SQLITE_INTEGER: - sqlite3_result_int64(pCtx, pSlot->iVal); - break; +static int idxLargestIndex(sqlite3 *db, int *pnMax, char **pzErr){ + int rc = SQLITE_OK; + const char *zMax = + "SELECT max(i.seqno) FROM " + " sqlite_schema AS s, " + " pragma_index_list(s.name) AS l, " + " pragma_index_info(l.name) AS i " + "WHERE s.type = 'table'"; + sqlite3_stmt *pMax = 0; - case SQLITE_FLOAT: - sqlite3_result_double(pCtx, pSlot->rVal); - break; + *pnMax = 0; + rc = idxPrepareStmt(db, &pMax, pzErr, zMax); + if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pMax) ){ + *pnMax = sqlite3_column_int(pMax, 0) + 1; + } + idxFinalize(&rc, pMax); - case SQLITE_BLOB: - sqlite3_result_blob(pCtx, pSlot->z, pSlot->n, SQLITE_TRANSIENT); - break; + return rc; +} - case SQLITE_TEXT: - sqlite3_result_text(pCtx, pSlot->z, pSlot->n, SQLITE_TRANSIENT); - break; +static int idxPopulateOneStat1( + sqlite3expert *p, + sqlite3_stmt *pIndexXInfo, + sqlite3_stmt *pWriteStat, + const char *zTab, + const char *zIdx, + char **pzErr +){ + char *zCols = 0; + char *zOrder = 0; + char *zQuery = 0; + int nCol = 0; + int i; + sqlite3_stmt *pQuery = 0; + int *aStat = 0; + int rc = SQLITE_OK; + + assert( p->iSample>0 ); + + /* Formulate the query text */ + sqlite3_bind_text(pIndexXInfo, 1, zIdx, -1, SQLITE_STATIC); + while( SQLITE_OK==rc && SQLITE_ROW==sqlite3_step(pIndexXInfo) ){ + const char *zComma = zCols==0 ? "" : ", "; + const char *zName = (const char*)sqlite3_column_text(pIndexXInfo, 0); + const char *zColl = (const char*)sqlite3_column_text(pIndexXInfo, 1); + zCols = idxAppendText(&rc, zCols, + "%sx.%Q IS rem(%d, x.%Q) COLLATE %s", zComma, zName, nCol, zName, zColl + ); + zOrder = idxAppendText(&rc, zOrder, "%s%d", zComma, ++nCol); + } + sqlite3_reset(pIndexXInfo); + if( rc==SQLITE_OK ){ + if( p->iSample==100 ){ + zQuery = sqlite3_mprintf( + "SELECT %s FROM %Q x ORDER BY %s", zCols, zTab, zOrder + ); + }else{ + zQuery = sqlite3_mprintf( + "SELECT %s FROM temp."UNIQUE_TABLE_NAME" x ORDER BY %s", zCols, zOrder + ); + } + } + sqlite3_free(zCols); + sqlite3_free(zOrder); + + /* Formulate the query text */ + if( rc==SQLITE_OK ){ + sqlite3 *dbrem = (p->iSample==100 ? p->db : p->dbv); + rc = idxPrepareStmt(dbrem, &pQuery, pzErr, zQuery); + } + sqlite3_free(zQuery); + + if( rc==SQLITE_OK ){ + aStat = (int*)idxMalloc(&rc, sizeof(int)*(nCol+1)); + } + if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pQuery) ){ + IdxHashEntry *pEntry; + char *zStat = 0; + for(i=0; i<=nCol; i++) aStat[i] = 1; + while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pQuery) ){ + aStat[0]++; + for(i=0; ieType = sqlite3_value_type(argv[1]); - switch( pSlot->eType ){ - case SQLITE_NULL: - /* no-op */ - break; - - case SQLITE_INTEGER: - pSlot->iVal = sqlite3_value_int64(argv[1]); - break; + if( rc==SQLITE_OK ){ + int s0 = aStat[0]; + zStat = sqlite3_mprintf("%d", s0); + if( zStat==0 ) rc = SQLITE_NOMEM; + for(i=1; rc==SQLITE_OK && i<=nCol; i++){ + zStat = idxAppendText(&rc, zStat, " %d", (s0+aStat[i]/2) / aStat[i]); + } + } - case SQLITE_FLOAT: - pSlot->rVal = sqlite3_value_double(argv[1]); - break; + if( rc==SQLITE_OK ){ + sqlite3_bind_text(pWriteStat, 1, zTab, -1, SQLITE_STATIC); + sqlite3_bind_text(pWriteStat, 2, zIdx, -1, SQLITE_STATIC); + sqlite3_bind_text(pWriteStat, 3, zStat, -1, SQLITE_STATIC); + sqlite3_step(pWriteStat); + rc = sqlite3_reset(pWriteStat); + } - case SQLITE_BLOB: - case SQLITE_TEXT: { - int nByte = sqlite3_value_bytes(argv[1]); - if( nByte>pSlot->nByte ){ - char *zNew = (char*)sqlite3_realloc(pSlot->z, nByte*2); - if( zNew==0 ){ - sqlite3_result_error_nomem(pCtx); - return; - } - pSlot->nByte = nByte*2; - pSlot->z = zNew; - } - pSlot->n = nByte; - if( pSlot->eType==SQLITE_BLOB ){ - memcpy(pSlot->z, sqlite3_value_blob(argv[1]), nByte); - }else{ - memcpy(pSlot->z, sqlite3_value_text(argv[1]), nByte); - } - break; - } + pEntry = idxHashFind(&p->hIdx, zIdx, STRLEN(zIdx)); + if( pEntry ){ + assert( pEntry->zVal2==0 ); + pEntry->zVal2 = zStat; + }else{ + sqlite3_free(zStat); } + } + sqlite3_free(aStat); + idxFinalize(&rc, pQuery); + + return rc; } -static int idxLargestIndex(sqlite3 *db, int *pnMax, char **pzErr){ - int rc = SQLITE_OK; - const char *zMax = - "SELECT max(i.seqno) FROM " - " sqlite_schema AS s, " - " pragma_index_list(s.name) AS l, " - " pragma_index_info(l.name) AS i " - "WHERE s.type = 'table'"; - sqlite3_stmt *pMax = 0; - - *pnMax = 0; - rc = idxPrepareStmt(db, &pMax, pzErr, zMax); - if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pMax) ){ - *pnMax = sqlite3_column_int(pMax, 0) + 1; - } - idxFinalize(&rc, pMax); +static int idxBuildSampleTable(sqlite3expert *p, const char *zTab){ + int rc; + char *zSql; - return rc; -} - -static int idxPopulateOneStat1( - sqlite3expert *p, - sqlite3_stmt *pIndexXInfo, - sqlite3_stmt *pWriteStat, - const char *zTab, - const char *zIdx, - char **pzErr -){ - char *zCols = 0; - char *zOrder = 0; - char *zQuery = 0; - int nCol = 0; - int i; - sqlite3_stmt *pQuery = 0; - int *aStat = 0; - int rc = SQLITE_OK; - - assert( p->iSample>0 ); - - /* Formulate the query text */ - sqlite3_bind_text(pIndexXInfo, 1, zIdx, -1, SQLITE_STATIC); - while( SQLITE_OK==rc && SQLITE_ROW==sqlite3_step(pIndexXInfo) ){ - const char *zComma = zCols==0 ? "" : ", "; - const char *zName = (const char*)sqlite3_column_text(pIndexXInfo, 0); - const char *zColl = (const char*)sqlite3_column_text(pIndexXInfo, 1); - zCols = idxAppendText(&rc, zCols, - "%sx.%Q IS rem(%d, x.%Q) COLLATE %s", zComma, zName, nCol, zName, zColl - ); - zOrder = idxAppendText(&rc, zOrder, "%s%d", zComma, ++nCol); - } - sqlite3_reset(pIndexXInfo); - if( rc==SQLITE_OK ){ - if( p->iSample==100 ){ - zQuery = sqlite3_mprintf( - "SELECT %s FROM %Q x ORDER BY %s", zCols, zTab, zOrder - ); - }else{ - zQuery = sqlite3_mprintf( - "SELECT %s FROM temp."UNIQUE_TABLE_NAME" x ORDER BY %s", zCols, zOrder - ); - } - } - sqlite3_free(zCols); - sqlite3_free(zOrder); - - /* Formulate the query text */ - if( rc==SQLITE_OK ){ - sqlite3 *dbrem = (p->iSample==100 ? p->db : p->dbv); - rc = idxPrepareStmt(dbrem, &pQuery, pzErr, zQuery); - } - sqlite3_free(zQuery); - - if( rc==SQLITE_OK ){ - aStat = (int*)idxMalloc(&rc, sizeof(int)*(nCol+1)); - } - if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pQuery) ){ - IdxHashEntry *pEntry; - char *zStat = 0; - for(i=0; i<=nCol; i++) aStat[i] = 1; - while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pQuery) ){ - aStat[0]++; - for(i=0; idbv,"DROP TABLE IF EXISTS temp."UNIQUE_TABLE_NAME,0,0,0); + if( rc!=SQLITE_OK ) return rc; - pEntry = idxHashFind(&p->hIdx, zIdx, STRLEN(zIdx)); - if( pEntry ){ - assert( pEntry->zVal2==0 ); - pEntry->zVal2 = zStat; - }else{ - sqlite3_free(zStat); - } - } - sqlite3_free(aStat); - idxFinalize(&rc, pQuery); - - return rc; -} - -static int idxBuildSampleTable(sqlite3expert *p, const char *zTab){ - int rc; - char *zSql; - - rc = sqlite3_exec(p->dbv,"DROP TABLE IF EXISTS temp."UNIQUE_TABLE_NAME,0,0,0); - if( rc!=SQLITE_OK ) return rc; - - zSql = sqlite3_mprintf( - "CREATE TABLE temp." UNIQUE_TABLE_NAME " AS SELECT * FROM %Q", zTab - ); - if( zSql==0 ) return SQLITE_NOMEM; - rc = sqlite3_exec(p->dbv, zSql, 0, 0, 0); - sqlite3_free(zSql); + zSql = sqlite3_mprintf( + "CREATE TABLE temp." UNIQUE_TABLE_NAME " AS SELECT * FROM %Q", zTab + ); + if( zSql==0 ) return SQLITE_NOMEM; + rc = sqlite3_exec(p->dbv, zSql, 0, 0, 0); + sqlite3_free(zSql); - return rc; + return rc; } /* @@ -10943,276 +10943,276 @@ static int idxBuildSampleTable(sqlite3expert *p, const char *zTab){ ** indexes have already been created in database sqlite3expert.dbm, this ** function populates sqlite_stat1 table in the same database. ** -** The stat1 data is generated by querying the +** The stat1 data is generated by querying the */ static int idxPopulateStat1(sqlite3expert *p, char **pzErr){ - int rc = SQLITE_OK; - int nMax =0; - struct IdxRemCtx *pCtx = 0; - struct IdxSampleCtx samplectx; - int i; - i64 iPrev = -100000; - sqlite3_stmt *pAllIndex = 0; - sqlite3_stmt *pIndexXInfo = 0; - sqlite3_stmt *pWrite = 0; - - const char *zAllIndex = - "SELECT s.rowid, s.name, l.name FROM " - " sqlite_schema AS s, " - " pragma_index_list(s.name) AS l " - "WHERE s.type = 'table'"; - const char *zIndexXInfo = - "SELECT name, coll FROM pragma_index_xinfo(?) WHERE key"; - const char *zWrite = "INSERT INTO sqlite_stat1 VALUES(?, ?, ?)"; - - /* If iSample==0, no sqlite_stat1 data is required. */ - if( p->iSample==0 ) return SQLITE_OK; - - rc = idxLargestIndex(p->dbm, &nMax, pzErr); - if( nMax<=0 || rc!=SQLITE_OK ) return rc; - - rc = sqlite3_exec(p->dbm, "ANALYZE; PRAGMA writable_schema=1", 0, 0, 0); - - if( rc==SQLITE_OK ){ - int nByte = sizeof(struct IdxRemCtx) + (sizeof(struct IdxRemSlot) * nMax); - pCtx = (struct IdxRemCtx*)idxMalloc(&rc, nByte); - } - - if( rc==SQLITE_OK ){ - sqlite3 *dbrem = (p->iSample==100 ? p->db : p->dbv); - rc = sqlite3_create_function( - dbrem, "rem", 2, SQLITE_UTF8, (void*)pCtx, idxRemFunc, 0, 0 - ); - } - if( rc==SQLITE_OK ){ - rc = sqlite3_create_function( - p->db, "sample", 0, SQLITE_UTF8, (void*)&samplectx, idxSampleFunc, 0, 0 - ); - } - - if( rc==SQLITE_OK ){ - pCtx->nSlot = nMax+1; - rc = idxPrepareStmt(p->dbm, &pAllIndex, pzErr, zAllIndex); - } - if( rc==SQLITE_OK ){ - rc = idxPrepareStmt(p->dbm, &pIndexXInfo, pzErr, zIndexXInfo); - } - if( rc==SQLITE_OK ){ - rc = idxPrepareStmt(p->dbm, &pWrite, pzErr, zWrite); - } - - while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pAllIndex) ){ - i64 iRowid = sqlite3_column_int64(pAllIndex, 0); - const char *zTab = (const char*)sqlite3_column_text(pAllIndex, 1); - const char *zIdx = (const char*)sqlite3_column_text(pAllIndex, 2); - if( p->iSample<100 && iPrev!=iRowid ){ - samplectx.target = (double)p->iSample / 100.0; - samplectx.iTarget = p->iSample; - samplectx.nRow = 0.0; - samplectx.nRet = 0.0; - rc = idxBuildSampleTable(p, zTab); - if( rc!=SQLITE_OK ) break; - } - rc = idxPopulateOneStat1(p, pIndexXInfo, pWrite, zTab, zIdx, pzErr); - iPrev = iRowid; - } - if( rc==SQLITE_OK && p->iSample<100 ){ - rc = sqlite3_exec(p->dbv, - "DROP TABLE IF EXISTS temp." UNIQUE_TABLE_NAME, 0,0,0 - ); - } + int rc = SQLITE_OK; + int nMax =0; + struct IdxRemCtx *pCtx = 0; + struct IdxSampleCtx samplectx; + int i; + i64 iPrev = -100000; + sqlite3_stmt *pAllIndex = 0; + sqlite3_stmt *pIndexXInfo = 0; + sqlite3_stmt *pWrite = 0; + + const char *zAllIndex = + "SELECT s.rowid, s.name, l.name FROM " + " sqlite_schema AS s, " + " pragma_index_list(s.name) AS l " + "WHERE s.type = 'table'"; + const char *zIndexXInfo = + "SELECT name, coll FROM pragma_index_xinfo(?) WHERE key"; + const char *zWrite = "INSERT INTO sqlite_stat1 VALUES(?, ?, ?)"; + + /* If iSample==0, no sqlite_stat1 data is required. */ + if( p->iSample==0 ) return SQLITE_OK; + + rc = idxLargestIndex(p->dbm, &nMax, pzErr); + if( nMax<=0 || rc!=SQLITE_OK ) return rc; + + rc = sqlite3_exec(p->dbm, "ANALYZE; PRAGMA writable_schema=1", 0, 0, 0); + + if( rc==SQLITE_OK ){ + int nByte = sizeof(struct IdxRemCtx) + (sizeof(struct IdxRemSlot) * nMax); + pCtx = (struct IdxRemCtx*)idxMalloc(&rc, nByte); + } + + if( rc==SQLITE_OK ){ + sqlite3 *dbrem = (p->iSample==100 ? p->db : p->dbv); + rc = sqlite3_create_function( + dbrem, "rem", 2, SQLITE_UTF8, (void*)pCtx, idxRemFunc, 0, 0 + ); + } + if( rc==SQLITE_OK ){ + rc = sqlite3_create_function( + p->db, "sample", 0, SQLITE_UTF8, (void*)&samplectx, idxSampleFunc, 0, 0 + ); + } + + if( rc==SQLITE_OK ){ + pCtx->nSlot = nMax+1; + rc = idxPrepareStmt(p->dbm, &pAllIndex, pzErr, zAllIndex); + } + if( rc==SQLITE_OK ){ + rc = idxPrepareStmt(p->dbm, &pIndexXInfo, pzErr, zIndexXInfo); + } + if( rc==SQLITE_OK ){ + rc = idxPrepareStmt(p->dbm, &pWrite, pzErr, zWrite); + } + + while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pAllIndex) ){ + i64 iRowid = sqlite3_column_int64(pAllIndex, 0); + const char *zTab = (const char*)sqlite3_column_text(pAllIndex, 1); + const char *zIdx = (const char*)sqlite3_column_text(pAllIndex, 2); + if( p->iSample<100 && iPrev!=iRowid ){ + samplectx.target = (double)p->iSample / 100.0; + samplectx.iTarget = p->iSample; + samplectx.nRow = 0.0; + samplectx.nRet = 0.0; + rc = idxBuildSampleTable(p, zTab); + if( rc!=SQLITE_OK ) break; + } + rc = idxPopulateOneStat1(p, pIndexXInfo, pWrite, zTab, zIdx, pzErr); + iPrev = iRowid; + } + if( rc==SQLITE_OK && p->iSample<100 ){ + rc = sqlite3_exec(p->dbv, + "DROP TABLE IF EXISTS temp." UNIQUE_TABLE_NAME, 0,0,0 + ); + } - idxFinalize(&rc, pAllIndex); - idxFinalize(&rc, pIndexXInfo); - idxFinalize(&rc, pWrite); + idxFinalize(&rc, pAllIndex); + idxFinalize(&rc, pIndexXInfo); + idxFinalize(&rc, pWrite); - if( pCtx ){ - for(i=0; inSlot; i++){ - sqlite3_free(pCtx->aSlot[i].z); - } - sqlite3_free(pCtx); + if( pCtx ){ + for(i=0; inSlot; i++){ + sqlite3_free(pCtx->aSlot[i].z); } + sqlite3_free(pCtx); + } - if( rc==SQLITE_OK ){ - rc = sqlite3_exec(p->dbm, "ANALYZE sqlite_schema", 0, 0, 0); - } + if( rc==SQLITE_OK ){ + rc = sqlite3_exec(p->dbm, "ANALYZE sqlite_schema", 0, 0, 0); + } - sqlite3_exec(p->db, "DROP TABLE IF EXISTS temp."UNIQUE_TABLE_NAME,0,0,0); - return rc; + sqlite3_exec(p->db, "DROP TABLE IF EXISTS temp."UNIQUE_TABLE_NAME,0,0,0); + return rc; } /* ** Allocate a new sqlite3expert object. */ sqlite3expert *sqlite3_expert_new(sqlite3 *db, char **pzErrmsg){ - int rc = SQLITE_OK; - sqlite3expert *pNew; + int rc = SQLITE_OK; + sqlite3expert *pNew; - pNew = (sqlite3expert*)idxMalloc(&rc, sizeof(sqlite3expert)); + pNew = (sqlite3expert*)idxMalloc(&rc, sizeof(sqlite3expert)); - /* Open two in-memory databases to work with. The "vtab database" (dbv) + /* Open two in-memory databases to work with. The "vtab database" (dbv) ** will contain a virtual table corresponding to each real table in ** the user database schema, and a copy of each view. It is used to ** collect information regarding the WHERE, ORDER BY and other clauses ** of the user's query. */ + if( rc==SQLITE_OK ){ + pNew->db = db; + pNew->iSample = 100; + rc = sqlite3_open(":memory:", &pNew->dbv); + } + if( rc==SQLITE_OK ){ + rc = sqlite3_open(":memory:", &pNew->dbm); if( rc==SQLITE_OK ){ - pNew->db = db; - pNew->iSample = 100; - rc = sqlite3_open(":memory:", &pNew->dbv); - } - if( rc==SQLITE_OK ){ - rc = sqlite3_open(":memory:", &pNew->dbm); - if( rc==SQLITE_OK ){ - sqlite3_db_config(pNew->dbm, SQLITE_DBCONFIG_TRIGGER_EQP, 1, (int*)0); - } + sqlite3_db_config(pNew->dbm, SQLITE_DBCONFIG_TRIGGER_EQP, 1, (int*)0); } + } + - - /* Copy the entire schema of database [db] into [dbm]. */ - if( rc==SQLITE_OK ){ - sqlite3_stmt *pSql; - rc = idxPrintfPrepareStmt(pNew->db, &pSql, pzErrmsg, - "SELECT sql FROM sqlite_schema WHERE name NOT LIKE 'sqlite_%%'" - " AND sql NOT LIKE 'CREATE VIRTUAL %%'" - ); - while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSql) ){ - const char *zSql = (const char*)sqlite3_column_text(pSql, 0); - rc = sqlite3_exec(pNew->dbm, zSql, 0, 0, pzErrmsg); - } - idxFinalize(&rc, pSql); + /* Copy the entire schema of database [db] into [dbm]. */ + if( rc==SQLITE_OK ){ + sqlite3_stmt *pSql; + rc = idxPrintfPrepareStmt(pNew->db, &pSql, pzErrmsg, + "SELECT sql FROM sqlite_schema WHERE name NOT LIKE 'sqlite_%%'" + " AND sql NOT LIKE 'CREATE VIRTUAL %%'" + ); + while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSql) ){ + const char *zSql = (const char*)sqlite3_column_text(pSql, 0); + rc = sqlite3_exec(pNew->dbm, zSql, 0, 0, pzErrmsg); } + idxFinalize(&rc, pSql); + } - /* Create the vtab schema */ - if( rc==SQLITE_OK ){ - rc = idxCreateVtabSchema(pNew, pzErrmsg); - } + /* Create the vtab schema */ + if( rc==SQLITE_OK ){ + rc = idxCreateVtabSchema(pNew, pzErrmsg); + } - /* Register the auth callback with dbv */ - if( rc==SQLITE_OK ){ - sqlite3_set_authorizer(pNew->dbv, idxAuthCallback, (void*)pNew); - } + /* Register the auth callback with dbv */ + if( rc==SQLITE_OK ){ + sqlite3_set_authorizer(pNew->dbv, idxAuthCallback, (void*)pNew); + } - /* If an error has occurred, free the new object and reutrn NULL. Otherwise, + /* If an error has occurred, free the new object and reutrn NULL. Otherwise, ** return the new sqlite3expert handle. */ - if( rc!=SQLITE_OK ){ - sqlite3_expert_destroy(pNew); - pNew = 0; - } - return pNew; + if( rc!=SQLITE_OK ){ + sqlite3_expert_destroy(pNew); + pNew = 0; + } + return pNew; } /* ** Configure an sqlite3expert object. */ int sqlite3_expert_config(sqlite3expert *p, int op, ...){ - int rc = SQLITE_OK; - va_list ap; - va_start(ap, op); - switch( op ){ - case EXPERT_CONFIG_SAMPLE: { - int iVal = va_arg(ap, int); - if( iVal<0 ) iVal = 0; - if( iVal>100 ) iVal = 100; - p->iSample = iVal; - break; - } - default: - rc = SQLITE_NOTFOUND; - break; + int rc = SQLITE_OK; + va_list ap; + va_start(ap, op); + switch( op ){ + case EXPERT_CONFIG_SAMPLE: { + int iVal = va_arg(ap, int); + if( iVal<0 ) iVal = 0; + if( iVal>100 ) iVal = 100; + p->iSample = iVal; + break; } + default: + rc = SQLITE_NOTFOUND; + break; + } - va_end(ap); - return rc; + va_end(ap); + return rc; } /* ** Add an SQL statement to the analysis. */ int sqlite3_expert_sql( - sqlite3expert *p, /* From sqlite3_expert_new() */ - const char *zSql, /* SQL statement to add */ - char **pzErr /* OUT: Error message (if any) */ + sqlite3expert *p, /* From sqlite3_expert_new() */ + const char *zSql, /* SQL statement to add */ + char **pzErr /* OUT: Error message (if any) */ ){ - IdxScan *pScanOrig = p->pScan; - IdxStatement *pStmtOrig = p->pStatement; - int rc = SQLITE_OK; - const char *zStmt = zSql; + IdxScan *pScanOrig = p->pScan; + IdxStatement *pStmtOrig = p->pStatement; + int rc = SQLITE_OK; + const char *zStmt = zSql; - if( p->bRun ) return SQLITE_MISUSE; + if( p->bRun ) return SQLITE_MISUSE; - while( rc==SQLITE_OK && zStmt && zStmt[0] ){ - sqlite3_stmt *pStmt = 0; - rc = sqlite3_prepare_v2(p->dbv, zStmt, -1, &pStmt, &zStmt); + while( rc==SQLITE_OK && zStmt && zStmt[0] ){ + sqlite3_stmt *pStmt = 0; + rc = sqlite3_prepare_v2(p->dbv, zStmt, -1, &pStmt, &zStmt); + if( rc==SQLITE_OK ){ + if( pStmt ){ + IdxStatement *pNew; + const char *z = sqlite3_sql(pStmt); + int n = STRLEN(z); + pNew = (IdxStatement*)idxMalloc(&rc, sizeof(IdxStatement) + n+1); if( rc==SQLITE_OK ){ - if( pStmt ){ - IdxStatement *pNew; - const char *z = sqlite3_sql(pStmt); - int n = STRLEN(z); - pNew = (IdxStatement*)idxMalloc(&rc, sizeof(IdxStatement) + n+1); - if( rc==SQLITE_OK ){ - pNew->zSql = (char*)&pNew[1]; - memcpy(pNew->zSql, z, n+1); - pNew->pNext = p->pStatement; - if( p->pStatement ) pNew->iId = p->pStatement->iId+1; - p->pStatement = pNew; - } - sqlite3_finalize(pStmt); - } - }else{ - idxDatabaseError(p->dbv, pzErr); + pNew->zSql = (char*)&pNew[1]; + memcpy(pNew->zSql, z, n+1); + pNew->pNext = p->pStatement; + if( p->pStatement ) pNew->iId = p->pStatement->iId+1; + p->pStatement = pNew; } + sqlite3_finalize(pStmt); + } + }else{ + idxDatabaseError(p->dbv, pzErr); } + } - if( rc!=SQLITE_OK ){ - idxScanFree(p->pScan, pScanOrig); - idxStatementFree(p->pStatement, pStmtOrig); - p->pScan = pScanOrig; - p->pStatement = pStmtOrig; - } + if( rc!=SQLITE_OK ){ + idxScanFree(p->pScan, pScanOrig); + idxStatementFree(p->pStatement, pStmtOrig); + p->pScan = pScanOrig; + p->pStatement = pStmtOrig; + } - return rc; + return rc; } int sqlite3_expert_analyze(sqlite3expert *p, char **pzErr){ - int rc; - IdxHashEntry *pEntry; - - /* Do trigger processing to collect any extra IdxScan structures */ - rc = idxProcessTriggers(p, pzErr); - - /* Create candidate indexes within the in-memory database file */ - if( rc==SQLITE_OK ){ - rc = idxCreateCandidates(p); - }else if ( rc==SQLITE_BUSY_TIMEOUT ){ - if( pzErr ) - *pzErr = sqlite3_mprintf("Cannot find a unique index name to propose."); - return rc; - } - - /* Generate the stat1 data */ - if( rc==SQLITE_OK ){ - rc = idxPopulateStat1(p, pzErr); - } - - /* Formulate the EXPERT_REPORT_CANDIDATES text */ - for(pEntry=p->hIdx.pFirst; pEntry; pEntry=pEntry->pNext){ - p->zCandidates = idxAppendText(&rc, p->zCandidates, - "%s;%s%s\n", pEntry->zVal, - pEntry->zVal2 ? " -- stat1: " : "", pEntry->zVal2 - ); - } + int rc; + IdxHashEntry *pEntry; + + /* Do trigger processing to collect any extra IdxScan structures */ + rc = idxProcessTriggers(p, pzErr); + + /* Create candidate indexes within the in-memory database file */ + if( rc==SQLITE_OK ){ + rc = idxCreateCandidates(p); + }else if ( rc==SQLITE_BUSY_TIMEOUT ){ + if( pzErr ) + *pzErr = sqlite3_mprintf("Cannot find a unique index name to propose."); + return rc; + } + + /* Generate the stat1 data */ + if( rc==SQLITE_OK ){ + rc = idxPopulateStat1(p, pzErr); + } + + /* Formulate the EXPERT_REPORT_CANDIDATES text */ + for(pEntry=p->hIdx.pFirst; pEntry; pEntry=pEntry->pNext){ + p->zCandidates = idxAppendText(&rc, p->zCandidates, + "%s;%s%s\n", pEntry->zVal, + pEntry->zVal2 ? " -- stat1: " : "", pEntry->zVal2 + ); + } - /* Figure out which of the candidate indexes are preferred by the query + /* Figure out which of the candidate indexes are preferred by the query ** planner and report the results to the user. */ - if( rc==SQLITE_OK ){ - rc = idxFindIndexes(p, pzErr); - } + if( rc==SQLITE_OK ){ + rc = idxFindIndexes(p, pzErr); + } - if( rc==SQLITE_OK ){ - p->bRun = 1; - } - return rc; + if( rc==SQLITE_OK ){ + p->bRun = 1; + } + return rc; } /* @@ -11220,52 +11220,52 @@ int sqlite3_expert_analyze(sqlite3expert *p, char **pzErr){ ** sqlite3expert using sqlite3_expert_sql(). */ int sqlite3_expert_count(sqlite3expert *p){ - int nRet = 0; - if( p->pStatement ) nRet = p->pStatement->iId+1; - return nRet; + int nRet = 0; + if( p->pStatement ) nRet = p->pStatement->iId+1; + return nRet; } /* ** Return a component of the report. */ const char *sqlite3_expert_report(sqlite3expert *p, int iStmt, int eReport){ - const char *zRet = 0; - IdxStatement *pStmt; - - if( p->bRun==0 ) return 0; - for(pStmt=p->pStatement; pStmt && pStmt->iId!=iStmt; pStmt=pStmt->pNext); - switch( eReport ){ - case EXPERT_REPORT_SQL: - if( pStmt ) zRet = pStmt->zSql; - break; - case EXPERT_REPORT_INDEXES: - if( pStmt ) zRet = pStmt->zIdx; - break; - case EXPERT_REPORT_PLAN: - if( pStmt ) zRet = pStmt->zEQP; - break; - case EXPERT_REPORT_CANDIDATES: - zRet = p->zCandidates; - break; - } - return zRet; + const char *zRet = 0; + IdxStatement *pStmt; + + if( p->bRun==0 ) return 0; + for(pStmt=p->pStatement; pStmt && pStmt->iId!=iStmt; pStmt=pStmt->pNext); + switch( eReport ){ + case EXPERT_REPORT_SQL: + if( pStmt ) zRet = pStmt->zSql; + break; + case EXPERT_REPORT_INDEXES: + if( pStmt ) zRet = pStmt->zIdx; + break; + case EXPERT_REPORT_PLAN: + if( pStmt ) zRet = pStmt->zEQP; + break; + case EXPERT_REPORT_CANDIDATES: + zRet = p->zCandidates; + break; + } + return zRet; } /* ** Free an sqlite3expert object. */ void sqlite3_expert_destroy(sqlite3expert *p){ - if( p ){ - sqlite3_close(p->dbm); - sqlite3_close(p->dbv); - idxScanFree(p->pScan, 0); - idxStatementFree(p->pStatement, 0); - idxTableFree(p->pTable); - idxWriteFree(p->pWrite); - idxHashClear(&p->hIdx); - sqlite3_free(p->zCandidates); - sqlite3_free(p); - } + if( p ){ + sqlite3_close(p->dbm); + sqlite3_close(p->dbv); + idxScanFree(p->pScan, 0); + idxStatementFree(p->pStatement, 0); + idxTableFree(p->pTable); + idxWriteFree(p->pWrite); + idxHashClear(&p->hIdx); + sqlite3_free(p->zCandidates); + sqlite3_free(p); + } } #endif /* ifndef SQLITE_OMIT_VIRTUALTABLE */ @@ -11320,7 +11320,7 @@ void sqlite3_expert_destroy(sqlite3expert *p){ ** INSERT INTO t1(rowid, a, b) VALUES(5, 'v', 'five'); ** INSERT INTO t1(rowid, a, b) VALUES(10, 'x', 'ten'); ** -** the sqlite_dbdata table contains, as well as from entries related to +** the sqlite_dbdata table contains, as well as from entries related to ** page 1, content equivalent to: ** ** INSERT INTO sqlite_dbdata(pgno, cell, field, value) VALUES @@ -11347,7 +11347,7 @@ void sqlite3_expert_destroy(sqlite3expert *p){ ** It contains one entry for each b-tree pointer between a parent and ** child page in the database. */ -#if !defined(SQLITEINT_H) +#if !defined(SQLITEINT_H) /* #include "sqlite3ext.h" */ /* typedef unsigned char u8; */ @@ -11357,42 +11357,42 @@ SQLITE_EXTENSION_INIT1 #include #include -#define DBDATA_PADDING_BYTES 100 +#define DBDATA_PADDING_BYTES 100 typedef struct DbdataTable DbdataTable; typedef struct DbdataCursor DbdataCursor; /* Cursor object */ struct DbdataCursor { - sqlite3_vtab_cursor base; /* Base class. Must be first */ - sqlite3_stmt *pStmt; /* For fetching database pages */ - - int iPgno; /* Current page number */ - u8 *aPage; /* Buffer containing page */ - int nPage; /* Size of aPage[] in bytes */ - int nCell; /* Number of cells on aPage[] */ - int iCell; /* Current cell number */ - int bOnePage; /* True to stop after one page */ - int szDb; - sqlite3_int64 iRowid; - - /* Only for the sqlite_dbdata table */ - u8 *pRec; /* Buffer containing current record */ - int nRec; /* Size of pRec[] in bytes */ - int nHdr; /* Size of header in bytes */ - int iField; /* Current field number */ - u8 *pHdrPtr; - u8 *pPtr; - - sqlite3_int64 iIntkey; /* Integer key value */ + sqlite3_vtab_cursor base; /* Base class. Must be first */ + sqlite3_stmt *pStmt; /* For fetching database pages */ + + int iPgno; /* Current page number */ + u8 *aPage; /* Buffer containing page */ + int nPage; /* Size of aPage[] in bytes */ + int nCell; /* Number of cells on aPage[] */ + int iCell; /* Current cell number */ + int bOnePage; /* True to stop after one page */ + int szDb; + sqlite3_int64 iRowid; + + /* Only for the sqlite_dbdata table */ + u8 *pRec; /* Buffer containing current record */ + int nRec; /* Size of pRec[] in bytes */ + int nHdr; /* Size of header in bytes */ + int iField; /* Current field number */ + u8 *pHdrPtr; + u8 *pPtr; + + sqlite3_int64 iIntkey; /* Integer key value */ }; /* Table object */ struct DbdataTable { - sqlite3_vtab base; /* Base class. Must be first */ - sqlite3 *db; /* The database connection */ - sqlite3_stmt *pStmt; /* For fetching database pages */ - int bPtr; /* True for sqlite3_dbptr table */ + sqlite3_vtab base; /* Base class. Must be first */ + sqlite3 *db; /* The database connection */ + sqlite3_stmt *pStmt; /* For fetching database pages */ + int bPtr; /* True for sqlite3_dbptr table */ }; /* Column and schema definitions for sqlite_dbdata */ @@ -11422,44 +11422,44 @@ struct DbdataTable { ")" /* -** Connect to an sqlite_dbdata (pAux==0) or sqlite_dbptr (pAux!=0) virtual +** Connect to an sqlite_dbdata (pAux==0) or sqlite_dbptr (pAux!=0) virtual ** table. */ static int dbdataConnect( - sqlite3 *db, - void *pAux, - int argc, const char *const*argv, - sqlite3_vtab **ppVtab, - char **pzErr + sqlite3 *db, + void *pAux, + int argc, const char *const*argv, + sqlite3_vtab **ppVtab, + char **pzErr ){ - DbdataTable *pTab = 0; - int rc = sqlite3_declare_vtab(db, pAux ? DBPTR_SCHEMA : DBDATA_SCHEMA); + DbdataTable *pTab = 0; + int rc = sqlite3_declare_vtab(db, pAux ? DBPTR_SCHEMA : DBDATA_SCHEMA); - if( rc==SQLITE_OK ){ - pTab = (DbdataTable*)sqlite3_malloc64(sizeof(DbdataTable)); - if( pTab==0 ){ - rc = SQLITE_NOMEM; - }else{ - memset(pTab, 0, sizeof(DbdataTable)); - pTab->db = db; - pTab->bPtr = (pAux!=0); - } + if( rc==SQLITE_OK ){ + pTab = (DbdataTable*)sqlite3_malloc64(sizeof(DbdataTable)); + if( pTab==0 ){ + rc = SQLITE_NOMEM; + }else{ + memset(pTab, 0, sizeof(DbdataTable)); + pTab->db = db; + pTab->bPtr = (pAux!=0); } + } - *ppVtab = (sqlite3_vtab*)pTab; - return rc; + *ppVtab = (sqlite3_vtab*)pTab; + return rc; } /* ** Disconnect from or destroy a sqlite_dbdata or sqlite_dbptr virtual table. */ static int dbdataDisconnect(sqlite3_vtab *pVtab){ - DbdataTable *pTab = (DbdataTable*)pVtab; - if( pTab ){ - sqlite3_finalize(pTab->pStmt); - sqlite3_free(pVtab); - } - return SQLITE_OK; + DbdataTable *pTab = (DbdataTable*)pVtab; + if( pTab ){ + sqlite3_finalize(pTab->pStmt); + sqlite3_free(pVtab); + } + return SQLITE_OK; } /* @@ -11476,113 +11476,113 @@ static int dbdataDisconnect(sqlite3_vtab *pVtab){ ** position 1. */ static int dbdataBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdx){ - DbdataTable *pTab = (DbdataTable*)tab; - int i; - int iSchema = -1; - int iPgno = -1; - int colSchema = (pTab->bPtr ? DBPTR_COLUMN_SCHEMA : DBDATA_COLUMN_SCHEMA); - - for(i=0; inConstraint; i++){ - struct sqlite3_index_constraint *p = &pIdx->aConstraint[i]; - if( p->op==SQLITE_INDEX_CONSTRAINT_EQ ){ - if( p->iColumn==colSchema ){ - if( p->usable==0 ) return SQLITE_CONSTRAINT; - iSchema = i; - } - if( p->iColumn==DBDATA_COLUMN_PGNO && p->usable ){ - iPgno = i; - } - } - } - - if( iSchema>=0 ){ - pIdx->aConstraintUsage[iSchema].argvIndex = 1; - pIdx->aConstraintUsage[iSchema].omit = 1; - } - if( iPgno>=0 ){ - pIdx->aConstraintUsage[iPgno].argvIndex = 1 + (iSchema>=0); - pIdx->aConstraintUsage[iPgno].omit = 1; - pIdx->estimatedCost = 100; - pIdx->estimatedRows = 50; - - if( pTab->bPtr==0 && pIdx->nOrderBy && pIdx->aOrderBy[0].desc==0 ){ - int iCol = pIdx->aOrderBy[0].iColumn; - if( pIdx->nOrderBy==1 ){ - pIdx->orderByConsumed = (iCol==0 || iCol==1); - }else if( pIdx->nOrderBy==2 && pIdx->aOrderBy[1].desc==0 && iCol==0 ){ - pIdx->orderByConsumed = (pIdx->aOrderBy[1].iColumn==1); - } - } - - }else{ - pIdx->estimatedCost = 100000000; - pIdx->estimatedRows = 1000000000; - } - pIdx->idxNum = (iSchema>=0 ? 0x01 : 0x00) | (iPgno>=0 ? 0x02 : 0x00); - return SQLITE_OK; + DbdataTable *pTab = (DbdataTable*)tab; + int i; + int iSchema = -1; + int iPgno = -1; + int colSchema = (pTab->bPtr ? DBPTR_COLUMN_SCHEMA : DBDATA_COLUMN_SCHEMA); + + for(i=0; inConstraint; i++){ + struct sqlite3_index_constraint *p = &pIdx->aConstraint[i]; + if( p->op==SQLITE_INDEX_CONSTRAINT_EQ ){ + if( p->iColumn==colSchema ){ + if( p->usable==0 ) return SQLITE_CONSTRAINT; + iSchema = i; + } + if( p->iColumn==DBDATA_COLUMN_PGNO && p->usable ){ + iPgno = i; + } + } + } + + if( iSchema>=0 ){ + pIdx->aConstraintUsage[iSchema].argvIndex = 1; + pIdx->aConstraintUsage[iSchema].omit = 1; + } + if( iPgno>=0 ){ + pIdx->aConstraintUsage[iPgno].argvIndex = 1 + (iSchema>=0); + pIdx->aConstraintUsage[iPgno].omit = 1; + pIdx->estimatedCost = 100; + pIdx->estimatedRows = 50; + + if( pTab->bPtr==0 && pIdx->nOrderBy && pIdx->aOrderBy[0].desc==0 ){ + int iCol = pIdx->aOrderBy[0].iColumn; + if( pIdx->nOrderBy==1 ){ + pIdx->orderByConsumed = (iCol==0 || iCol==1); + }else if( pIdx->nOrderBy==2 && pIdx->aOrderBy[1].desc==0 && iCol==0 ){ + pIdx->orderByConsumed = (pIdx->aOrderBy[1].iColumn==1); + } + } + + }else{ + pIdx->estimatedCost = 100000000; + pIdx->estimatedRows = 1000000000; + } + pIdx->idxNum = (iSchema>=0 ? 0x01 : 0x00) | (iPgno>=0 ? 0x02 : 0x00); + return SQLITE_OK; } /* ** Open a new sqlite_dbdata or sqlite_dbptr cursor. */ static int dbdataOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){ - DbdataCursor *pCsr; + DbdataCursor *pCsr; - pCsr = (DbdataCursor*)sqlite3_malloc64(sizeof(DbdataCursor)); - if( pCsr==0 ){ - return SQLITE_NOMEM; - }else{ - memset(pCsr, 0, sizeof(DbdataCursor)); - pCsr->base.pVtab = pVTab; - } + pCsr = (DbdataCursor*)sqlite3_malloc64(sizeof(DbdataCursor)); + if( pCsr==0 ){ + return SQLITE_NOMEM; + }else{ + memset(pCsr, 0, sizeof(DbdataCursor)); + pCsr->base.pVtab = pVTab; + } - *ppCursor = (sqlite3_vtab_cursor *)pCsr; - return SQLITE_OK; + *ppCursor = (sqlite3_vtab_cursor *)pCsr; + return SQLITE_OK; } /* -** Restore a cursor object to the state it was in when first allocated +** Restore a cursor object to the state it was in when first allocated ** by dbdataOpen(). */ static void dbdataResetCursor(DbdataCursor *pCsr){ - DbdataTable *pTab = (DbdataTable*)(pCsr->base.pVtab); - if( pTab->pStmt==0 ){ - pTab->pStmt = pCsr->pStmt; - }else{ - sqlite3_finalize(pCsr->pStmt); - } - pCsr->pStmt = 0; - pCsr->iPgno = 1; - pCsr->iCell = 0; - pCsr->iField = 0; - pCsr->bOnePage = 0; - sqlite3_free(pCsr->aPage); - sqlite3_free(pCsr->pRec); - pCsr->pRec = 0; - pCsr->aPage = 0; + DbdataTable *pTab = (DbdataTable*)(pCsr->base.pVtab); + if( pTab->pStmt==0 ){ + pTab->pStmt = pCsr->pStmt; + }else{ + sqlite3_finalize(pCsr->pStmt); + } + pCsr->pStmt = 0; + pCsr->iPgno = 1; + pCsr->iCell = 0; + pCsr->iField = 0; + pCsr->bOnePage = 0; + sqlite3_free(pCsr->aPage); + sqlite3_free(pCsr->pRec); + pCsr->pRec = 0; + pCsr->aPage = 0; } /* ** Close an sqlite_dbdata or sqlite_dbptr cursor. */ static int dbdataClose(sqlite3_vtab_cursor *pCursor){ - DbdataCursor *pCsr = (DbdataCursor*)pCursor; - dbdataResetCursor(pCsr); - sqlite3_free(pCsr); - return SQLITE_OK; + DbdataCursor *pCsr = (DbdataCursor*)pCursor; + dbdataResetCursor(pCsr); + sqlite3_free(pCsr); + return SQLITE_OK; } -/* -** Utility methods to decode 16 and 32-bit big-endian unsigned integers. +/* +** Utility methods to decode 16 and 32-bit big-endian unsigned integers. */ static unsigned int get_uint16(unsigned char *a){ - return (a[0]<<8)|a[1]; + return (a[0]<<8)|a[1]; } static unsigned int get_uint32(unsigned char *a){ - return ((unsigned int)a[0]<<24) - | ((unsigned int)a[1]<<16) - | ((unsigned int)a[2]<<8) - | ((unsigned int)a[3]); + return ((unsigned int)a[0]<<24) + | ((unsigned int)a[1]<<16) + | ((unsigned int)a[2]<<8) + | ((unsigned int)a[3]); } /* @@ -11596,53 +11596,53 @@ static unsigned int get_uint32(unsigned char *a){ ** return an SQLite error code. */ static int dbdataLoadPage( - DbdataCursor *pCsr, /* Cursor object */ - unsigned int pgno, /* Page number of page to load */ - u8 **ppPage, /* OUT: pointer to page buffer */ - int *pnPage /* OUT: Size of (*ppPage) in bytes */ + DbdataCursor *pCsr, /* Cursor object */ + unsigned int pgno, /* Page number of page to load */ + u8 **ppPage, /* OUT: pointer to page buffer */ + int *pnPage /* OUT: Size of (*ppPage) in bytes */ ){ - int rc2; - int rc = SQLITE_OK; - sqlite3_stmt *pStmt = pCsr->pStmt; - - *ppPage = 0; - *pnPage = 0; - sqlite3_bind_int64(pStmt, 2, pgno); - if( SQLITE_ROW==sqlite3_step(pStmt) ){ - int nCopy = sqlite3_column_bytes(pStmt, 0); - if( nCopy>0 ){ - u8 *pPage; - pPage = (u8*)sqlite3_malloc64(nCopy + DBDATA_PADDING_BYTES); - if( pPage==0 ){ - rc = SQLITE_NOMEM; - }else{ - const u8 *pCopy = sqlite3_column_blob(pStmt, 0); - memcpy(pPage, pCopy, nCopy); - memset(&pPage[nCopy], 0, DBDATA_PADDING_BYTES); - } - *ppPage = pPage; - *pnPage = nCopy; - } + int rc2; + int rc = SQLITE_OK; + sqlite3_stmt *pStmt = pCsr->pStmt; + + *ppPage = 0; + *pnPage = 0; + sqlite3_bind_int64(pStmt, 2, pgno); + if( SQLITE_ROW==sqlite3_step(pStmt) ){ + int nCopy = sqlite3_column_bytes(pStmt, 0); + if( nCopy>0 ){ + u8 *pPage; + pPage = (u8*)sqlite3_malloc64(nCopy + DBDATA_PADDING_BYTES); + if( pPage==0 ){ + rc = SQLITE_NOMEM; + }else{ + const u8 *pCopy = sqlite3_column_blob(pStmt, 0); + memcpy(pPage, pCopy, nCopy); + memset(&pPage[nCopy], 0, DBDATA_PADDING_BYTES); + } + *ppPage = pPage; + *pnPage = nCopy; } - rc2 = sqlite3_reset(pStmt); - if( rc==SQLITE_OK ) rc = rc2; + } + rc2 = sqlite3_reset(pStmt); + if( rc==SQLITE_OK ) rc = rc2; - return rc; + return rc; } /* ** Read a varint. Put the value in *pVal and return the number of bytes. */ static int dbdataGetVarint(const u8 *z, sqlite3_int64 *pVal){ - sqlite3_int64 v = 0; - int i; - for(i=0; i<8; i++){ - v = (v<<7) + (z[i]&0x7f); - if( (z[i]&0x80)==0 ){ *pVal = v; return i+1; } - } - v = (v<<8) + (z[i]&0xff); - *pVal = v; - return 9; + sqlite3_int64 v = 0; + int i; + for(i=0; i<8; i++){ + v = (v<<7) + (z[i]&0x7f); + if( (z[i]&0x80)==0 ){ *pVal = v; return i+1; } + } + v = (v<<8) + (z[i]&0xff); + *pVal = v; + return 9; } /* @@ -11650,29 +11650,29 @@ static int dbdataGetVarint(const u8 *z, sqlite3_int64 *pVal){ ** eType. */ static int dbdataValueBytes(int eType){ - switch( eType ){ - case 0: case 8: case 9: - case 10: case 11: - return 0; - case 1: - return 1; - case 2: - return 2; - case 3: - return 3; - case 4: - return 4; - case 5: - return 6; - case 6: - case 7: - return 8; - default: - if( eType>0 ){ - return ((eType-12) / 2); - } - return 0; - } + switch( eType ){ + case 0: case 8: case 9: + case 10: case 11: + return 0; + case 1: + return 1; + case 2: + return 2; + case 3: + return 3; + case 4: + return 4; + case 5: + return 6; + case 6: + case 7: + return 8; + default: + if( eType>0 ){ + return ((eType-12) / 2); + } + return 0; + } } /* @@ -11680,399 +11680,399 @@ static int dbdataValueBytes(int eType){ ** result of context object pCtx. */ static void dbdataValue( - sqlite3_context *pCtx, - int eType, - u8 *pData, - int nData + sqlite3_context *pCtx, + int eType, + u8 *pData, + int nData ){ - if( eType>=0 && dbdataValueBytes(eType)<=nData ){ + if( eType>=0 && dbdataValueBytes(eType)<=nData ){ + switch( eType ){ + case 0: + case 10: + case 11: + sqlite3_result_null(pCtx); + break; + + case 8: + sqlite3_result_int(pCtx, 0); + break; + case 9: + sqlite3_result_int(pCtx, 1); + break; + + case 1: case 2: case 3: case 4: case 5: case 6: case 7: { + sqlite3_uint64 v = (signed char)pData[0]; + pData++; switch( eType ){ - case 0: - case 10: - case 11: - sqlite3_result_null(pCtx); - break; - - case 8: - sqlite3_result_int(pCtx, 0); - break; - case 9: - sqlite3_result_int(pCtx, 1); - break; - - case 1: case 2: case 3: case 4: case 5: case 6: case 7: { - sqlite3_uint64 v = (signed char)pData[0]; - pData++; - switch( eType ){ - case 7: - case 6: v = (v<<16) + (pData[0]<<8) + pData[1]; pData += 2; - case 5: v = (v<<16) + (pData[0]<<8) + pData[1]; pData += 2; - case 4: v = (v<<8) + pData[0]; pData++; - case 3: v = (v<<8) + pData[0]; pData++; - case 2: v = (v<<8) + pData[0]; pData++; - } - - if( eType==7 ){ - double r; - memcpy(&r, &v, sizeof(r)); - sqlite3_result_double(pCtx, r); - }else{ - sqlite3_result_int64(pCtx, (sqlite3_int64)v); - } - break; - } - - default: { - int n = ((eType-12) / 2); - if( eType % 2 ){ - sqlite3_result_text(pCtx, (const char*)pData, n, SQLITE_TRANSIENT); - }else{ - sqlite3_result_blob(pCtx, pData, n, SQLITE_TRANSIENT); - } - } + case 7: + case 6: v = (v<<16) + (pData[0]<<8) + pData[1]; pData += 2; + case 5: v = (v<<16) + (pData[0]<<8) + pData[1]; pData += 2; + case 4: v = (v<<8) + pData[0]; pData++; + case 3: v = (v<<8) + pData[0]; pData++; + case 2: v = (v<<8) + pData[0]; pData++; + } + + if( eType==7 ){ + double r; + memcpy(&r, &v, sizeof(r)); + sqlite3_result_double(pCtx, r); + }else{ + sqlite3_result_int64(pCtx, (sqlite3_int64)v); + } + break; + } + + default: { + int n = ((eType-12) / 2); + if( eType % 2 ){ + sqlite3_result_text(pCtx, (const char*)pData, n, SQLITE_TRANSIENT); + }else{ + sqlite3_result_blob(pCtx, pData, n, SQLITE_TRANSIENT); } + } } + } } /* ** Move an sqlite_dbdata or sqlite_dbptr cursor to the next entry. */ static int dbdataNext(sqlite3_vtab_cursor *pCursor){ - DbdataCursor *pCsr = (DbdataCursor*)pCursor; - DbdataTable *pTab = (DbdataTable*)pCursor->pVtab; + DbdataCursor *pCsr = (DbdataCursor*)pCursor; + DbdataTable *pTab = (DbdataTable*)pCursor->pVtab; - pCsr->iRowid++; - while( 1 ){ - int rc; - int iOff = (pCsr->iPgno==1 ? 100 : 0); - int bNextPage = 0; - - if( pCsr->aPage==0 ){ - while( 1 ){ - if( pCsr->bOnePage==0 && pCsr->iPgno>pCsr->szDb ) return SQLITE_OK; - rc = dbdataLoadPage(pCsr, pCsr->iPgno, &pCsr->aPage, &pCsr->nPage); - if( rc!=SQLITE_OK ) return rc; - if( pCsr->aPage ) break; - pCsr->iPgno++; - } - pCsr->iCell = pTab->bPtr ? -2 : 0; - pCsr->nCell = get_uint16(&pCsr->aPage[iOff+3]); + pCsr->iRowid++; + while( 1 ){ + int rc; + int iOff = (pCsr->iPgno==1 ? 100 : 0); + int bNextPage = 0; + + if( pCsr->aPage==0 ){ + while( 1 ){ + if( pCsr->bOnePage==0 && pCsr->iPgno>pCsr->szDb ) return SQLITE_OK; + rc = dbdataLoadPage(pCsr, pCsr->iPgno, &pCsr->aPage, &pCsr->nPage); + if( rc!=SQLITE_OK ) return rc; + if( pCsr->aPage ) break; + pCsr->iPgno++; + } + pCsr->iCell = pTab->bPtr ? -2 : 0; + pCsr->nCell = get_uint16(&pCsr->aPage[iOff+3]); + } + + if( pTab->bPtr ){ + if( pCsr->aPage[iOff]!=0x02 && pCsr->aPage[iOff]!=0x05 ){ + pCsr->iCell = pCsr->nCell; + } + pCsr->iCell++; + if( pCsr->iCell>=pCsr->nCell ){ + sqlite3_free(pCsr->aPage); + pCsr->aPage = 0; + if( pCsr->bOnePage ) return SQLITE_OK; + pCsr->iPgno++; + }else{ + return SQLITE_OK; + } + }else{ + /* If there is no record loaded, load it now. */ + if( pCsr->pRec==0 ){ + int bHasRowid = 0; + int nPointer = 0; + sqlite3_int64 nPayload = 0; + sqlite3_int64 nHdr = 0; + int iHdr; + int U, X; + int nLocal; + + switch( pCsr->aPage[iOff] ){ + case 0x02: + nPointer = 4; + break; + case 0x0a: + break; + case 0x0d: + bHasRowid = 1; + break; + default: + /* This is not a b-tree page with records on it. Continue. */ + pCsr->iCell = pCsr->nCell; + break; } - if( pTab->bPtr ){ - if( pCsr->aPage[iOff]!=0x02 && pCsr->aPage[iOff]!=0x05 ){ - pCsr->iCell = pCsr->nCell; - } - pCsr->iCell++; - if( pCsr->iCell>=pCsr->nCell ){ - sqlite3_free(pCsr->aPage); - pCsr->aPage = 0; - if( pCsr->bOnePage ) return SQLITE_OK; - pCsr->iPgno++; - }else{ - return SQLITE_OK; - } + if( pCsr->iCell>=pCsr->nCell ){ + bNextPage = 1; }else{ - /* If there is no record loaded, load it now. */ - if( pCsr->pRec==0 ){ - int bHasRowid = 0; - int nPointer = 0; - sqlite3_int64 nPayload = 0; - sqlite3_int64 nHdr = 0; - int iHdr; - int U, X; - int nLocal; - - switch( pCsr->aPage[iOff] ){ - case 0x02: - nPointer = 4; - break; - case 0x0a: - break; - case 0x0d: - bHasRowid = 1; - break; - default: - /* This is not a b-tree page with records on it. Continue. */ - pCsr->iCell = pCsr->nCell; - break; - } - - if( pCsr->iCell>=pCsr->nCell ){ - bNextPage = 1; - }else{ - - iOff += 8 + nPointer + pCsr->iCell*2; - if( iOff>pCsr->nPage ){ - bNextPage = 1; - }else{ - iOff = get_uint16(&pCsr->aPage[iOff]); - } - - /* For an interior node cell, skip past the child-page number */ - iOff += nPointer; - - /* Load the "byte of payload including overflow" field */ - if( bNextPage || iOff>pCsr->nPage ){ - bNextPage = 1; - }else{ - iOff += dbdataGetVarint(&pCsr->aPage[iOff], &nPayload); - } - - /* If this is a leaf intkey cell, load the rowid */ - if( bHasRowid && !bNextPage && iOffnPage ){ - iOff += dbdataGetVarint(&pCsr->aPage[iOff], &pCsr->iIntkey); - } - - /* Figure out how much data to read from the local page */ - U = pCsr->nPage; - if( bHasRowid ){ - X = U-35; - }else{ - X = ((U-12)*64/255)-23; - } - if( nPayload<=X ){ - nLocal = nPayload; - }else{ - int M, K; - M = ((U-12)*32/255)-23; - K = M+((nPayload-M)%(U-4)); - if( K<=X ){ - nLocal = K; - }else{ - nLocal = M; - } - } - - if( bNextPage || nLocal+iOff>pCsr->nPage ){ - bNextPage = 1; - }else{ - - /* Allocate space for payload. And a bit more to catch small buffer - ** overruns caused by attempting to read a varint or similar from - ** near the end of a corrupt record. */ - pCsr->pRec = (u8*)sqlite3_malloc64(nPayload+DBDATA_PADDING_BYTES); - if( pCsr->pRec==0 ) return SQLITE_NOMEM; - memset(pCsr->pRec, 0, nPayload+DBDATA_PADDING_BYTES); - pCsr->nRec = nPayload; - - /* Load the nLocal bytes of payload */ - memcpy(pCsr->pRec, &pCsr->aPage[iOff], nLocal); - iOff += nLocal; - - /* Load content from overflow pages */ - if( nPayload>nLocal ){ - sqlite3_int64 nRem = nPayload - nLocal; - unsigned int pgnoOvfl = get_uint32(&pCsr->aPage[iOff]); - while( nRem>0 ){ - u8 *aOvfl = 0; - int nOvfl = 0; - int nCopy; - rc = dbdataLoadPage(pCsr, pgnoOvfl, &aOvfl, &nOvfl); - assert( rc!=SQLITE_OK || aOvfl==0 || nOvfl==pCsr->nPage ); - if( rc!=SQLITE_OK ) return rc; - if( aOvfl==0 ) break; - - nCopy = U-4; - if( nCopy>nRem ) nCopy = nRem; - memcpy(&pCsr->pRec[nPayload-nRem], &aOvfl[4], nCopy); - nRem -= nCopy; - - pgnoOvfl = get_uint32(aOvfl); - sqlite3_free(aOvfl); - } - } - - iHdr = dbdataGetVarint(pCsr->pRec, &nHdr); - pCsr->nHdr = nHdr; - pCsr->pHdrPtr = &pCsr->pRec[iHdr]; - pCsr->pPtr = &pCsr->pRec[pCsr->nHdr]; - pCsr->iField = (bHasRowid ? -1 : 0); - } - } + + iOff += 8 + nPointer + pCsr->iCell*2; + if( iOff>pCsr->nPage ){ + bNextPage = 1; + }else{ + iOff = get_uint16(&pCsr->aPage[iOff]); + } + + /* For an interior node cell, skip past the child-page number */ + iOff += nPointer; + + /* Load the "byte of payload including overflow" field */ + if( bNextPage || iOff>pCsr->nPage ){ + bNextPage = 1; + }else{ + iOff += dbdataGetVarint(&pCsr->aPage[iOff], &nPayload); + } + + /* If this is a leaf intkey cell, load the rowid */ + if( bHasRowid && !bNextPage && iOffnPage ){ + iOff += dbdataGetVarint(&pCsr->aPage[iOff], &pCsr->iIntkey); + } + + /* Figure out how much data to read from the local page */ + U = pCsr->nPage; + if( bHasRowid ){ + X = U-35; + }else{ + X = ((U-12)*64/255)-23; + } + if( nPayload<=X ){ + nLocal = nPayload; + }else{ + int M, K; + M = ((U-12)*32/255)-23; + K = M+((nPayload-M)%(U-4)); + if( K<=X ){ + nLocal = K; }else{ - pCsr->iField++; - if( pCsr->iField>0 ){ - sqlite3_int64 iType; - if( pCsr->pHdrPtr>&pCsr->pRec[pCsr->nRec] ){ - bNextPage = 1; - }else{ - pCsr->pHdrPtr += dbdataGetVarint(pCsr->pHdrPtr, &iType); - pCsr->pPtr += dbdataValueBytes(iType); - } - } + nLocal = M; } + } - if( bNextPage ){ - sqlite3_free(pCsr->aPage); - sqlite3_free(pCsr->pRec); - pCsr->aPage = 0; - pCsr->pRec = 0; - if( pCsr->bOnePage ) return SQLITE_OK; - pCsr->iPgno++; - }else{ - if( pCsr->iField<0 || pCsr->pHdrPtr<&pCsr->pRec[pCsr->nHdr] ){ - return SQLITE_OK; - } + if( bNextPage || nLocal+iOff>pCsr->nPage ){ + bNextPage = 1; + }else{ - /* Advance to the next cell. The next iteration of the loop will load + /* Allocate space for payload. And a bit more to catch small buffer + ** overruns caused by attempting to read a varint or similar from + ** near the end of a corrupt record. */ + pCsr->pRec = (u8*)sqlite3_malloc64(nPayload+DBDATA_PADDING_BYTES); + if( pCsr->pRec==0 ) return SQLITE_NOMEM; + memset(pCsr->pRec, 0, nPayload+DBDATA_PADDING_BYTES); + pCsr->nRec = nPayload; + + /* Load the nLocal bytes of payload */ + memcpy(pCsr->pRec, &pCsr->aPage[iOff], nLocal); + iOff += nLocal; + + /* Load content from overflow pages */ + if( nPayload>nLocal ){ + sqlite3_int64 nRem = nPayload - nLocal; + unsigned int pgnoOvfl = get_uint32(&pCsr->aPage[iOff]); + while( nRem>0 ){ + u8 *aOvfl = 0; + int nOvfl = 0; + int nCopy; + rc = dbdataLoadPage(pCsr, pgnoOvfl, &aOvfl, &nOvfl); + assert( rc!=SQLITE_OK || aOvfl==0 || nOvfl==pCsr->nPage ); + if( rc!=SQLITE_OK ) return rc; + if( aOvfl==0 ) break; + + nCopy = U-4; + if( nCopy>nRem ) nCopy = nRem; + memcpy(&pCsr->pRec[nPayload-nRem], &aOvfl[4], nCopy); + nRem -= nCopy; + + pgnoOvfl = get_uint32(aOvfl); + sqlite3_free(aOvfl); + } + } + + iHdr = dbdataGetVarint(pCsr->pRec, &nHdr); + pCsr->nHdr = nHdr; + pCsr->pHdrPtr = &pCsr->pRec[iHdr]; + pCsr->pPtr = &pCsr->pRec[pCsr->nHdr]; + pCsr->iField = (bHasRowid ? -1 : 0); + } + } + }else{ + pCsr->iField++; + if( pCsr->iField>0 ){ + sqlite3_int64 iType; + if( pCsr->pHdrPtr>&pCsr->pRec[pCsr->nRec] ){ + bNextPage = 1; + }else{ + pCsr->pHdrPtr += dbdataGetVarint(pCsr->pHdrPtr, &iType); + pCsr->pPtr += dbdataValueBytes(iType); + } + } + } + + if( bNextPage ){ + sqlite3_free(pCsr->aPage); + sqlite3_free(pCsr->pRec); + pCsr->aPage = 0; + pCsr->pRec = 0; + if( pCsr->bOnePage ) return SQLITE_OK; + pCsr->iPgno++; + }else{ + if( pCsr->iField<0 || pCsr->pHdrPtr<&pCsr->pRec[pCsr->nHdr] ){ + return SQLITE_OK; + } + + /* Advance to the next cell. The next iteration of the loop will load ** the record and so on. */ - sqlite3_free(pCsr->pRec); - pCsr->pRec = 0; - pCsr->iCell++; - } - } + sqlite3_free(pCsr->pRec); + pCsr->pRec = 0; + pCsr->iCell++; + } } + } - assert( !"can't get here" ); - return SQLITE_OK; + assert( !"can't get here" ); + return SQLITE_OK; } -/* +/* ** Return true if the cursor is at EOF. */ static int dbdataEof(sqlite3_vtab_cursor *pCursor){ - DbdataCursor *pCsr = (DbdataCursor*)pCursor; - return pCsr->aPage==0; + DbdataCursor *pCsr = (DbdataCursor*)pCursor; + return pCsr->aPage==0; } -/* +/* ** Determine the size in pages of database zSchema (where zSchema is -** "main", "temp" or the name of an attached database) and set +** "main", "temp" or the name of an attached database) and set ** pCsr->szDb accordingly. If successful, return SQLITE_OK. Otherwise, ** an SQLite error code. */ static int dbdataDbsize(DbdataCursor *pCsr, const char *zSchema){ - DbdataTable *pTab = (DbdataTable*)pCsr->base.pVtab; - char *zSql = 0; - int rc, rc2; - sqlite3_stmt *pStmt = 0; - - zSql = sqlite3_mprintf("PRAGMA %Q.page_count", zSchema); - if( zSql==0 ) return SQLITE_NOMEM; - rc = sqlite3_prepare_v2(pTab->db, zSql, -1, &pStmt, 0); - sqlite3_free(zSql); - if( rc==SQLITE_OK && sqlite3_step(pStmt)==SQLITE_ROW ){ - pCsr->szDb = sqlite3_column_int(pStmt, 0); - } - rc2 = sqlite3_finalize(pStmt); - if( rc==SQLITE_OK ) rc = rc2; - return rc; -} - -/* + DbdataTable *pTab = (DbdataTable*)pCsr->base.pVtab; + char *zSql = 0; + int rc, rc2; + sqlite3_stmt *pStmt = 0; + + zSql = sqlite3_mprintf("PRAGMA %Q.page_count", zSchema); + if( zSql==0 ) return SQLITE_NOMEM; + rc = sqlite3_prepare_v2(pTab->db, zSql, -1, &pStmt, 0); + sqlite3_free(zSql); + if( rc==SQLITE_OK && sqlite3_step(pStmt)==SQLITE_ROW ){ + pCsr->szDb = sqlite3_column_int(pStmt, 0); + } + rc2 = sqlite3_finalize(pStmt); + if( rc==SQLITE_OK ) rc = rc2; + return rc; +} + +/* ** xFilter method for sqlite_dbdata and sqlite_dbptr. */ static int dbdataFilter( - sqlite3_vtab_cursor *pCursor, - int idxNum, const char *idxStr, - int argc, sqlite3_value **argv + sqlite3_vtab_cursor *pCursor, + int idxNum, const char *idxStr, + int argc, sqlite3_value **argv ){ - DbdataCursor *pCsr = (DbdataCursor*)pCursor; - DbdataTable *pTab = (DbdataTable*)pCursor->pVtab; - int rc = SQLITE_OK; - const char *zSchema = "main"; - - dbdataResetCursor(pCsr); - assert( pCsr->iPgno==1 ); - if( idxNum & 0x01 ){ - zSchema = (const char*)sqlite3_value_text(argv[0]); - } - if( idxNum & 0x02 ){ - pCsr->iPgno = sqlite3_value_int(argv[(idxNum & 0x01)]); - pCsr->bOnePage = 1; + DbdataCursor *pCsr = (DbdataCursor*)pCursor; + DbdataTable *pTab = (DbdataTable*)pCursor->pVtab; + int rc = SQLITE_OK; + const char *zSchema = "main"; + + dbdataResetCursor(pCsr); + assert( pCsr->iPgno==1 ); + if( idxNum & 0x01 ){ + zSchema = (const char*)sqlite3_value_text(argv[0]); + } + if( idxNum & 0x02 ){ + pCsr->iPgno = sqlite3_value_int(argv[(idxNum & 0x01)]); + pCsr->bOnePage = 1; + }else{ + pCsr->nPage = dbdataDbsize(pCsr, zSchema); + rc = dbdataDbsize(pCsr, zSchema); + } + + if( rc==SQLITE_OK ){ + if( pTab->pStmt ){ + pCsr->pStmt = pTab->pStmt; + pTab->pStmt = 0; }else{ - pCsr->nPage = dbdataDbsize(pCsr, zSchema); - rc = dbdataDbsize(pCsr, zSchema); - } - - if( rc==SQLITE_OK ){ - if( pTab->pStmt ){ - pCsr->pStmt = pTab->pStmt; - pTab->pStmt = 0; + rc = sqlite3_prepare_v2(pTab->db, + "SELECT data FROM sqlite_dbpage(?) WHERE pgno=?", -1, + &pCsr->pStmt, 0 + ); + } + } + if( rc==SQLITE_OK ){ + rc = sqlite3_bind_text(pCsr->pStmt, 1, zSchema, -1, SQLITE_TRANSIENT); + }else{ + pTab->base.zErrMsg = sqlite3_mprintf("%s", sqlite3_errmsg(pTab->db)); + } + if( rc==SQLITE_OK ){ + rc = dbdataNext(pCursor); + } + return rc; +} + +/* +** Return a column for the sqlite_dbdata or sqlite_dbptr table. +*/ +static int dbdataColumn( + sqlite3_vtab_cursor *pCursor, + sqlite3_context *ctx, + int i +){ + DbdataCursor *pCsr = (DbdataCursor*)pCursor; + DbdataTable *pTab = (DbdataTable*)pCursor->pVtab; + if( pTab->bPtr ){ + switch( i ){ + case DBPTR_COLUMN_PGNO: + sqlite3_result_int64(ctx, pCsr->iPgno); + break; + case DBPTR_COLUMN_CHILD: { + int iOff = pCsr->iPgno==1 ? 100 : 0; + if( pCsr->iCell<0 ){ + iOff += 8; }else{ - rc = sqlite3_prepare_v2(pTab->db, - "SELECT data FROM sqlite_dbpage(?) WHERE pgno=?", -1, - &pCsr->pStmt, 0 - ); + iOff += 12 + pCsr->iCell*2; + if( iOff>pCsr->nPage ) return SQLITE_OK; + iOff = get_uint16(&pCsr->aPage[iOff]); } + if( iOff<=pCsr->nPage ){ + sqlite3_result_int64(ctx, get_uint32(&pCsr->aPage[iOff])); + } + break; + } } - if( rc==SQLITE_OK ){ - rc = sqlite3_bind_text(pCsr->pStmt, 1, zSchema, -1, SQLITE_TRANSIENT); - }else{ - pTab->base.zErrMsg = sqlite3_mprintf("%s", sqlite3_errmsg(pTab->db)); - } - if( rc==SQLITE_OK ){ - rc = dbdataNext(pCursor); + }else{ + switch( i ){ + case DBDATA_COLUMN_PGNO: + sqlite3_result_int64(ctx, pCsr->iPgno); + break; + case DBDATA_COLUMN_CELL: + sqlite3_result_int(ctx, pCsr->iCell); + break; + case DBDATA_COLUMN_FIELD: + sqlite3_result_int(ctx, pCsr->iField); + break; + case DBDATA_COLUMN_VALUE: { + if( pCsr->iField<0 ){ + sqlite3_result_int64(ctx, pCsr->iIntkey); + }else{ + sqlite3_int64 iType; + dbdataGetVarint(pCsr->pHdrPtr, &iType); + dbdataValue( + ctx, iType, pCsr->pPtr, &pCsr->pRec[pCsr->nRec] - pCsr->pPtr + ); + } + break; + } } - return rc; + } + return SQLITE_OK; } -/* -** Return a column for the sqlite_dbdata or sqlite_dbptr table. -*/ -static int dbdataColumn( - sqlite3_vtab_cursor *pCursor, - sqlite3_context *ctx, - int i -){ - DbdataCursor *pCsr = (DbdataCursor*)pCursor; - DbdataTable *pTab = (DbdataTable*)pCursor->pVtab; - if( pTab->bPtr ){ - switch( i ){ - case DBPTR_COLUMN_PGNO: - sqlite3_result_int64(ctx, pCsr->iPgno); - break; - case DBPTR_COLUMN_CHILD: { - int iOff = pCsr->iPgno==1 ? 100 : 0; - if( pCsr->iCell<0 ){ - iOff += 8; - }else{ - iOff += 12 + pCsr->iCell*2; - if( iOff>pCsr->nPage ) return SQLITE_OK; - iOff = get_uint16(&pCsr->aPage[iOff]); - } - if( iOff<=pCsr->nPage ){ - sqlite3_result_int64(ctx, get_uint32(&pCsr->aPage[iOff])); - } - break; - } - } - }else{ - switch( i ){ - case DBDATA_COLUMN_PGNO: - sqlite3_result_int64(ctx, pCsr->iPgno); - break; - case DBDATA_COLUMN_CELL: - sqlite3_result_int(ctx, pCsr->iCell); - break; - case DBDATA_COLUMN_FIELD: - sqlite3_result_int(ctx, pCsr->iField); - break; - case DBDATA_COLUMN_VALUE: { - if( pCsr->iField<0 ){ - sqlite3_result_int64(ctx, pCsr->iIntkey); - }else{ - sqlite3_int64 iType; - dbdataGetVarint(pCsr->pHdrPtr, &iType); - dbdataValue( - ctx, iType, pCsr->pPtr, &pCsr->pRec[pCsr->nRec] - pCsr->pPtr - ); - } - break; - } - } - } - return SQLITE_OK; -} - -/* -** Return the rowid for an sqlite_dbdata or sqlite_dptr table. +/* +** Return the rowid for an sqlite_dbdata or sqlite_dptr table. */ static int dbdataRowid(sqlite3_vtab_cursor *pCursor, sqlite_int64 *pRowid){ - DbdataCursor *pCsr = (DbdataCursor*)pCursor; - *pRowid = pCsr->iRowid; - return SQLITE_OK; + DbdataCursor *pCsr = (DbdataCursor*)pCursor; + *pRowid = pCsr->iRowid; + return SQLITE_OK; } @@ -12080,50 +12080,50 @@ static int dbdataRowid(sqlite3_vtab_cursor *pCursor, sqlite_int64 *pRowid){ ** Invoke this routine to register the "sqlite_dbdata" virtual table module */ static int sqlite3DbdataRegister(sqlite3 *db){ - static sqlite3_module dbdata_module = { - 0, /* iVersion */ - 0, /* xCreate */ - dbdataConnect, /* xConnect */ - dbdataBestIndex, /* xBestIndex */ - dbdataDisconnect, /* xDisconnect */ - 0, /* xDestroy */ - dbdataOpen, /* xOpen - open a cursor */ - dbdataClose, /* xClose - close a cursor */ - dbdataFilter, /* xFilter - configure scan constraints */ - dbdataNext, /* xNext - advance a cursor */ - dbdataEof, /* xEof - check for end of scan */ - dbdataColumn, /* xColumn - read data */ - dbdataRowid, /* xRowid - read data */ - 0, /* xUpdate */ - 0, /* xBegin */ - 0, /* xSync */ - 0, /* xCommit */ - 0, /* xRollback */ - 0, /* xFindMethod */ - 0, /* xRename */ - 0, /* xSavepoint */ - 0, /* xRelease */ - 0, /* xRollbackTo */ - 0 /* xShadowName */ - }; - - int rc = sqlite3_create_module(db, "sqlite_dbdata", &dbdata_module, 0); - if( rc==SQLITE_OK ){ - rc = sqlite3_create_module(db, "sqlite_dbptr", &dbdata_module, (void*)1); - } - return rc; + static sqlite3_module dbdata_module = { + 0, /* iVersion */ + 0, /* xCreate */ + dbdataConnect, /* xConnect */ + dbdataBestIndex, /* xBestIndex */ + dbdataDisconnect, /* xDisconnect */ + 0, /* xDestroy */ + dbdataOpen, /* xOpen - open a cursor */ + dbdataClose, /* xClose - close a cursor */ + dbdataFilter, /* xFilter - configure scan constraints */ + dbdataNext, /* xNext - advance a cursor */ + dbdataEof, /* xEof - check for end of scan */ + dbdataColumn, /* xColumn - read data */ + dbdataRowid, /* xRowid - read data */ + 0, /* xUpdate */ + 0, /* xBegin */ + 0, /* xSync */ + 0, /* xCommit */ + 0, /* xRollback */ + 0, /* xFindMethod */ + 0, /* xRename */ + 0, /* xSavepoint */ + 0, /* xRelease */ + 0, /* xRollbackTo */ + 0 /* xShadowName */ + }; + + int rc = sqlite3_create_module(db, "sqlite_dbdata", &dbdata_module, 0); + if( rc==SQLITE_OK ){ + rc = sqlite3_create_module(db, "sqlite_dbptr", &dbdata_module, (void*)1); + } + return rc; } #ifdef _WIN32 #endif int sqlite3_dbdata_init( - sqlite3 *db, - char **pzErrMsg, - const sqlite3_api_routines *pApi + sqlite3 *db, + char **pzErrMsg, + const sqlite3_api_routines *pApi ){ - SQLITE_EXTENSION_INIT2(pApi); - return sqlite3DbdataRegister(db); + SQLITE_EXTENSION_INIT2(pApi); + return sqlite3DbdataRegister(db); } /************************* End ../ext/misc/dbdata.c ********************/ @@ -12135,34 +12135,34 @@ int sqlite3_dbdata_init( */ typedef struct OpenSession OpenSession; struct OpenSession { - char *zName; /* Symbolic name for this session */ - int nFilter; /* Number of xFilter rejection GLOB patterns */ - char **azFilter; /* Array of xFilter rejection GLOB patterns */ - sqlite3_session *p; /* The open session */ + char *zName; /* Symbolic name for this session */ + int nFilter; /* Number of xFilter rejection GLOB patterns */ + char **azFilter; /* Array of xFilter rejection GLOB patterns */ + sqlite3_session *p; /* The open session */ }; #endif typedef struct ExpertInfo ExpertInfo; struct ExpertInfo { - sqlite3expert *pExpert; - int bVerbose; + sqlite3expert *pExpert; + int bVerbose; }; /* A single line in the EQP output */ typedef struct EQPGraphRow EQPGraphRow; struct EQPGraphRow { - int iEqpId; /* ID for this row */ - int iParentId; /* ID of the parent row */ - EQPGraphRow *pNext; /* Next row in sequence */ - char zText[1]; /* Text to display for this row */ + int iEqpId; /* ID for this row */ + int iParentId; /* ID of the parent row */ + EQPGraphRow *pNext; /* Next row in sequence */ + char zText[1]; /* Text to display for this row */ }; /* All EQP output is collected into an instance of the following */ typedef struct EQPGraph EQPGraph; struct EQPGraph { - EQPGraphRow *pRow; /* Linked list of all rows of the EQP output */ - EQPGraphRow *pLast; /* Last element of the pRow list */ - char zPrefix[100]; /* Graph prefix */ + EQPGraphRow *pRow; /* Linked list of all rows of the EQP output */ + EQPGraphRow *pLast; /* Last element of the pRow list */ + char zPrefix[100]; /* Graph prefix */ }; /* @@ -12171,72 +12171,72 @@ struct EQPGraph { */ typedef struct ShellState ShellState; struct ShellState { - sqlite3 *db; /* The database */ - u8 autoExplain; /* Automatically turn on .explain mode */ - u8 autoEQP; /* Run EXPLAIN QUERY PLAN prior to seach SQL stmt */ - u8 autoEQPtest; /* autoEQP is in test mode */ - u8 autoEQPtrace; /* autoEQP is in trace mode */ - u8 scanstatsOn; /* True to display scan stats before each finalize */ - u8 openMode; /* SHELL_OPEN_NORMAL, _APPENDVFS, or _ZIPFILE */ - u8 doXdgOpen; /* Invoke start/open/xdg-open in output_reset() */ - u8 nEqpLevel; /* Depth of the EQP output graph */ - u8 eTraceType; /* SHELL_TRACE_* value for type of trace */ - u8 bSafeMode; /* True to prohibit unsafe operations */ - u8 bSafeModePersist; /* The long-term value of bSafeMode */ - unsigned statsOn; /* True to display memory stats before each finalize */ - unsigned mEqpLines; /* Mask of veritical lines in the EQP output graph */ - int outCount; /* Revert to stdout when reaching zero */ - int cnt; /* Number of records displayed so far */ - int lineno; /* Line number of last line read from in */ - int openFlags; /* Additional flags to open. (SQLITE_OPEN_NOFOLLOW) */ - FILE *in; /* Read commands from this stream */ - FILE *out; /* Write results here */ - FILE *traceOut; /* Output for sqlite3_trace() */ - int nErr; /* Number of errors seen */ - int mode; /* An output mode setting */ - int modePrior; /* Saved mode */ - int cMode; /* temporary output mode for the current query */ - int normalMode; /* Output mode before ".explain on" */ - int writableSchema; /* True if PRAGMA writable_schema=ON */ - int showHeader; /* True to show column names in List or Column mode */ - int nCheck; /* Number of ".check" commands run */ - unsigned nProgress; /* Number of progress callbacks encountered */ - unsigned mxProgress; /* Maximum progress callbacks before failing */ - unsigned flgProgress; /* Flags for the progress callback */ - unsigned shellFlgs; /* Various flags */ - unsigned priorShFlgs; /* Saved copy of flags */ - sqlite3_int64 szMax; /* --maxsize argument to .open */ - char *zDestTable; /* Name of destination table when MODE_Insert */ - char *zTempFile; /* Temporary file that might need deleting */ - char zTestcase[30]; /* Name of current test case */ - char colSeparator[20]; /* Column separator character for several modes */ - char rowSeparator[20]; /* Row separator character for MODE_Ascii */ - char colSepPrior[20]; /* Saved column separator */ - char rowSepPrior[20]; /* Saved row separator */ - int *colWidth; /* Requested width of each column in columnar modes */ - int *actualWidth; /* Actual width of each column */ - int nWidth; /* Number of slots in colWidth[] and actualWidth[] */ - char nullValue[20]; /* The text to print when a NULL comes back from + sqlite3 *db; /* The database */ + u8 autoExplain; /* Automatically turn on .explain mode */ + u8 autoEQP; /* Run EXPLAIN QUERY PLAN prior to seach SQL stmt */ + u8 autoEQPtest; /* autoEQP is in test mode */ + u8 autoEQPtrace; /* autoEQP is in trace mode */ + u8 scanstatsOn; /* True to display scan stats before each finalize */ + u8 openMode; /* SHELL_OPEN_NORMAL, _APPENDVFS, or _ZIPFILE */ + u8 doXdgOpen; /* Invoke start/open/xdg-open in output_reset() */ + u8 nEqpLevel; /* Depth of the EQP output graph */ + u8 eTraceType; /* SHELL_TRACE_* value for type of trace */ + u8 bSafeMode; /* True to prohibit unsafe operations */ + u8 bSafeModePersist; /* The long-term value of bSafeMode */ + unsigned statsOn; /* True to display memory stats before each finalize */ + unsigned mEqpLines; /* Mask of veritical lines in the EQP output graph */ + int outCount; /* Revert to stdout when reaching zero */ + int cnt; /* Number of records displayed so far */ + int lineno; /* Line number of last line read from in */ + int openFlags; /* Additional flags to open. (SQLITE_OPEN_NOFOLLOW) */ + FILE *in; /* Read commands from this stream */ + FILE *out; /* Write results here */ + FILE *traceOut; /* Output for sqlite3_trace() */ + int nErr; /* Number of errors seen */ + int mode; /* An output mode setting */ + int modePrior; /* Saved mode */ + int cMode; /* temporary output mode for the current query */ + int normalMode; /* Output mode before ".explain on" */ + int writableSchema; /* True if PRAGMA writable_schema=ON */ + int showHeader; /* True to show column names in List or Column mode */ + int nCheck; /* Number of ".check" commands run */ + unsigned nProgress; /* Number of progress callbacks encountered */ + unsigned mxProgress; /* Maximum progress callbacks before failing */ + unsigned flgProgress; /* Flags for the progress callback */ + unsigned shellFlgs; /* Various flags */ + unsigned priorShFlgs; /* Saved copy of flags */ + sqlite3_int64 szMax; /* --maxsize argument to .open */ + char *zDestTable; /* Name of destination table when MODE_Insert */ + char *zTempFile; /* Temporary file that might need deleting */ + char zTestcase[30]; /* Name of current test case */ + char colSeparator[20]; /* Column separator character for several modes */ + char rowSeparator[20]; /* Row separator character for MODE_Ascii */ + char colSepPrior[20]; /* Saved column separator */ + char rowSepPrior[20]; /* Saved row separator */ + int *colWidth; /* Requested width of each column in columnar modes */ + int *actualWidth; /* Actual width of each column */ + int nWidth; /* Number of slots in colWidth[] and actualWidth[] */ + char nullValue[20]; /* The text to print when a NULL comes back from ** the database */ - char outfile[FILENAME_MAX]; /* Filename for *out */ - sqlite3_stmt *pStmt; /* Current statement if any. */ - FILE *pLog; /* Write log output here */ - struct AuxDb { /* Storage space for auxiliary database connections */ - sqlite3 *db; /* Connection pointer */ - const char *zDbFilename; /* Filename used to open the connection */ - char *zFreeOnClose; /* Free this memory allocation on close */ + char outfile[FILENAME_MAX]; /* Filename for *out */ + sqlite3_stmt *pStmt; /* Current statement if any. */ + FILE *pLog; /* Write log output here */ + struct AuxDb { /* Storage space for auxiliary database connections */ + sqlite3 *db; /* Connection pointer */ + const char *zDbFilename; /* Filename used to open the connection */ + char *zFreeOnClose; /* Free this memory allocation on close */ #if defined(SQLITE_ENABLE_SESSION) - int nSession; /* Number of active sessions */ - OpenSession aSession[4]; /* Array of sessions. [0] is in focus. */ + int nSession; /* Number of active sessions */ + OpenSession aSession[4]; /* Array of sessions. [0] is in focus. */ #endif - } aAuxDb[5], /* Array of all database connections */ - *pAuxDb; /* Currently active database connection */ - int *aiIndent; /* Array of indents used in MODE_Explain */ - int nIndent; /* Size of array aiIndent[] */ - int iIndent; /* Index of current op in aiIndent[] */ - char *zNonce; /* Nonce for temporary safe-mode excapes */ - EQPGraph sGraph; /* Information for the graphical EXPLAIN QUERY PLAN */ - ExpertInfo expert; /* Valid if previous command was ".expert OPT..." */ + } aAuxDb[5], /* Array of all database connections */ + *pAuxDb; /* Currently active database connection */ + int *aiIndent; /* Array of indents used in MODE_Explain */ + int nIndent; /* Size of array aiIndent[] */ + int iIndent; /* Index of current op in aiIndent[] */ + char *zNonce; /* Nonce for temporary safe-mode excapes */ + EQPGraph sGraph; /* Information for the graphical EXPLAIN QUERY PLAN */ + ExpertInfo expert; /* Valid if previous command was ".expert OPT..." */ }; @@ -12313,23 +12313,23 @@ struct ShellState { #define MODE_Box 16 /* Unicode box-drawing characters */ static const char *modeDescr[] = { - "line", - "column", - "list", - "semi", - "html", - "insert", - "quote", - "tcl", - "csv", - "explain", - "ascii", - "prettyprint", - "eqp", - "json", - "markdown", - "table", - "box" + "line", + "column", + "list", + "semi", + "html", + "insert", + "quote", + "tcl", + "csv", + "explain", + "ascii", + "prettyprint", + "eqp", + "json", + "markdown", + "table", + "box" }; /* @@ -12349,10 +12349,10 @@ static const char *modeDescr[] = { ** A callback for the sqlite3_log() interface. */ static void shellLog(void *pArg, int iErrCode, const char *zMsg){ - ShellState *p = (ShellState*)pArg; - if( p->pLog==0 ) return; - utf8_printf(p->pLog, "(%d) %s\n", iErrCode, zMsg); - fflush(p->pLog); + ShellState *p = (ShellState*)pArg; + if( p->pLog==0 ) return; + utf8_printf(p->pLog, "(%d) %s\n", iErrCode, zMsg); + fflush(p->pLog); } /* @@ -12362,14 +12362,14 @@ static void shellLog(void *pArg, int iErrCode, const char *zMsg){ ** adding a newline at the end, and then return X. */ static void shellPutsFunc( - sqlite3_context *pCtx, - int nVal, - sqlite3_value **apVal + sqlite3_context *pCtx, + int nVal, + sqlite3_value **apVal ){ - ShellState *p = (ShellState*)sqlite3_user_data(pCtx); - (void)nVal; - utf8_printf(p->out, "%s\n", sqlite3_value_text(apVal[0])); - sqlite3_result_value(pCtx, apVal[0]); + ShellState *p = (ShellState*)sqlite3_user_data(pCtx); + (void)nVal; + utf8_printf(p->out, "%s\n", sqlite3_value_text(apVal[0])); + sqlite3_result_value(pCtx, apVal[0]); } /* @@ -12377,20 +12377,20 @@ static void shellPutsFunc( ** and exit immediately. */ static void failIfSafeMode( - ShellState *p, - const char *zErrMsg, - ... + ShellState *p, + const char *zErrMsg, + ... ){ - if( p->bSafeMode ){ - va_list ap; - char *zMsg; - va_start(ap, zErrMsg); - zMsg = sqlite3_vmprintf(zErrMsg, ap); - va_end(ap); - raw_printf(stderr, "line %d: ", p->lineno); - utf8_printf(stderr, "%s\n", zMsg); - exit(1); - } + if( p->bSafeMode ){ + va_list ap; + char *zMsg; + va_start(ap, zErrMsg); + zMsg = sqlite3_vmprintf(zErrMsg, ap); + va_end(ap); + raw_printf(stderr, "line %d: ", p->lineno); + utf8_printf(stderr, "%s\n", zMsg); + exit(1); + } } /* @@ -12411,128 +12411,128 @@ static void failIfSafeMode( */ #ifndef SQLITE_NOHAVE_SYSTEM static void editFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv + sqlite3_context *context, + int argc, + sqlite3_value **argv ){ - const char *zEditor; - char *zTempFile = 0; - sqlite3 *db; - char *zCmd = 0; - int bBin; - int rc; - int hasCRNL = 0; - FILE *f = 0; - sqlite3_int64 sz; - sqlite3_int64 x; - unsigned char *p = 0; - - if( argc==2 ){ - zEditor = (const char*)sqlite3_value_text(argv[1]); - }else{ - zEditor = getenv("VISUAL"); - } - if( zEditor==0 ){ - sqlite3_result_error(context, "no editor for edit()", -1); - return; - } - if( sqlite3_value_type(argv[0])==SQLITE_NULL ){ - sqlite3_result_error(context, "NULL input to edit()", -1); - return; - } - db = sqlite3_context_db_handle(context); - zTempFile = 0; - sqlite3_file_control(db, 0, SQLITE_FCNTL_TEMPFILENAME, &zTempFile); + const char *zEditor; + char *zTempFile = 0; + sqlite3 *db; + char *zCmd = 0; + int bBin; + int rc; + int hasCRNL = 0; + FILE *f = 0; + sqlite3_int64 sz; + sqlite3_int64 x; + unsigned char *p = 0; + + if( argc==2 ){ + zEditor = (const char*)sqlite3_value_text(argv[1]); + }else{ + zEditor = getenv("VISUAL"); + } + if( zEditor==0 ){ + sqlite3_result_error(context, "no editor for edit()", -1); + return; + } + if( sqlite3_value_type(argv[0])==SQLITE_NULL ){ + sqlite3_result_error(context, "NULL input to edit()", -1); + return; + } + db = sqlite3_context_db_handle(context); + zTempFile = 0; + sqlite3_file_control(db, 0, SQLITE_FCNTL_TEMPFILENAME, &zTempFile); + if( zTempFile==0 ){ + sqlite3_uint64 r = 0; + sqlite3_randomness(sizeof(r), &r); + zTempFile = sqlite3_mprintf("temp%llx", r); if( zTempFile==0 ){ - sqlite3_uint64 r = 0; - sqlite3_randomness(sizeof(r), &r); - zTempFile = sqlite3_mprintf("temp%llx", r); - if( zTempFile==0 ){ - sqlite3_result_error_nomem(context); - return; - } + sqlite3_result_error_nomem(context); + return; } - bBin = sqlite3_value_type(argv[0])==SQLITE_BLOB; - /* When writing the file to be edited, do \n to \r\n conversions on systems + } + bBin = sqlite3_value_type(argv[0])==SQLITE_BLOB; + /* When writing the file to be edited, do \n to \r\n conversions on systems ** that want \r\n line endings */ - f = fopen(zTempFile, bBin ? "wb" : "w"); - if( f==0 ){ - sqlite3_result_error(context, "edit() cannot open temp file", -1); - goto edit_func_end; - } - sz = sqlite3_value_bytes(argv[0]); - if( bBin ){ - x = fwrite(sqlite3_value_blob(argv[0]), 1, (size_t)sz, f); - }else{ - const char *z = (const char*)sqlite3_value_text(argv[0]); - /* Remember whether or not the value originally contained \r\n */ - if( z && strstr(z,"\r\n")!=0 ) hasCRNL = 1; - x = fwrite(sqlite3_value_text(argv[0]), 1, (size_t)sz, f); - } - fclose(f); - f = 0; - if( x!=sz ){ - sqlite3_result_error(context, "edit() could not write the whole file", -1); - goto edit_func_end; - } - zCmd = sqlite3_mprintf("%s \"%s\"", zEditor, zTempFile); - if( zCmd==0 ){ - sqlite3_result_error_nomem(context); - goto edit_func_end; - } - rc = system(zCmd); - sqlite3_free(zCmd); - if( rc ){ - sqlite3_result_error(context, "EDITOR returned non-zero", -1); - goto edit_func_end; - } - f = fopen(zTempFile, "rb"); - if( f==0 ){ - sqlite3_result_error(context, - "edit() cannot reopen temp file after edit", -1); - goto edit_func_end; - } - fseek(f, 0, SEEK_END); - sz = ftell(f); - rewind(f); - p = sqlite3_malloc64( sz+1 ); - if( p==0 ){ - sqlite3_result_error_nomem(context); - goto edit_func_end; - } - x = fread(p, 1, (size_t)sz, f); - fclose(f); - f = 0; - if( x!=sz ){ - sqlite3_result_error(context, "could not read back the whole file", -1); - goto edit_func_end; - } - if( bBin ){ - sqlite3_result_blob64(context, p, sz, sqlite3_free); + f = fopen(zTempFile, bBin ? "wb" : "w"); + if( f==0 ){ + sqlite3_result_error(context, "edit() cannot open temp file", -1); + goto edit_func_end; + } + sz = sqlite3_value_bytes(argv[0]); + if( bBin ){ + x = fwrite(sqlite3_value_blob(argv[0]), 1, (size_t)sz, f); + }else{ + const char *z = (const char*)sqlite3_value_text(argv[0]); + /* Remember whether or not the value originally contained \r\n */ + if( z && strstr(z,"\r\n")!=0 ) hasCRNL = 1; + x = fwrite(sqlite3_value_text(argv[0]), 1, (size_t)sz, f); + } + fclose(f); + f = 0; + if( x!=sz ){ + sqlite3_result_error(context, "edit() could not write the whole file", -1); + goto edit_func_end; + } + zCmd = sqlite3_mprintf("%s \"%s\"", zEditor, zTempFile); + if( zCmd==0 ){ + sqlite3_result_error_nomem(context); + goto edit_func_end; + } + rc = system(zCmd); + sqlite3_free(zCmd); + if( rc ){ + sqlite3_result_error(context, "EDITOR returned non-zero", -1); + goto edit_func_end; + } + f = fopen(zTempFile, "rb"); + if( f==0 ){ + sqlite3_result_error(context, + "edit() cannot reopen temp file after edit", -1); + goto edit_func_end; + } + fseek(f, 0, SEEK_END); + sz = ftell(f); + rewind(f); + p = sqlite3_malloc64( sz+1 ); + if( p==0 ){ + sqlite3_result_error_nomem(context); + goto edit_func_end; + } + x = fread(p, 1, (size_t)sz, f); + fclose(f); + f = 0; + if( x!=sz ){ + sqlite3_result_error(context, "could not read back the whole file", -1); + goto edit_func_end; + } + if( bBin ){ + sqlite3_result_blob64(context, p, sz, sqlite3_free); + }else{ + sqlite3_int64 i, j; + if( hasCRNL ){ + /* If the original contains \r\n then do no conversions back to \n */ }else{ - sqlite3_int64 i, j; - if( hasCRNL ){ - /* If the original contains \r\n then do no conversions back to \n */ - }else{ - /* If the file did not originally contain \r\n then convert any new + /* If the file did not originally contain \r\n then convert any new ** \r\n back into \n */ - for(i=j=0; imodePrior = p->mode; - p->priorShFlgs = p->shellFlgs; - memcpy(p->colSepPrior, p->colSeparator, sizeof(p->colSeparator)); - memcpy(p->rowSepPrior, p->rowSeparator, sizeof(p->rowSeparator)); + p->modePrior = p->mode; + p->priorShFlgs = p->shellFlgs; + memcpy(p->colSepPrior, p->colSeparator, sizeof(p->colSeparator)); + memcpy(p->rowSepPrior, p->rowSeparator, sizeof(p->rowSeparator)); } static void outputModePop(ShellState *p){ - p->mode = p->modePrior; - p->shellFlgs = p->priorShFlgs; - memcpy(p->colSeparator, p->colSepPrior, sizeof(p->colSeparator)); - memcpy(p->rowSeparator, p->rowSepPrior, sizeof(p->rowSeparator)); + p->mode = p->modePrior; + p->shellFlgs = p->priorShFlgs; + memcpy(p->colSeparator, p->colSepPrior, sizeof(p->colSeparator)); + memcpy(p->rowSeparator, p->rowSepPrior, sizeof(p->rowSeparator)); } /* ** Output the given string as a hex-encoded blob (eg. X'1234' ) */ static void output_hex_blob(FILE *out, const void *pBlob, int nBlob){ - int i; - char *zBlob = (char *)pBlob; - raw_printf(out,"X'"); - for(i=0; i0 ){ - utf8_printf(out,"%.*s",i,z); - } - if( z[i]=='<' ){ - raw_printf(out,"<"); - }else if( z[i]=='&' ){ - raw_printf(out,"&"); - }else if( z[i]=='>' ){ - raw_printf(out,">"); - }else if( z[i]=='\"' ){ - raw_printf(out,"""); - }else if( z[i]=='\'' ){ - raw_printf(out,"'"); - }else{ - break; - } - z += i + 1; + int i; + if( z==0 ) z = ""; + while( *z ){ + for(i=0; z[i] + && z[i]!='<' + && z[i]!='&' + && z[i]!='>' + && z[i]!='\"' + && z[i]!='\''; + i++){} + if( i>0 ){ + utf8_printf(out,"%.*s",i,z); + } + if( z[i]=='<' ){ + raw_printf(out,"<"); + }else if( z[i]=='&' ){ + raw_printf(out,"&"); + }else if( z[i]=='>' ){ + raw_printf(out,">"); + }else if( z[i]=='\"' ){ + raw_printf(out,"""); + }else if( z[i]=='\'' ){ + raw_printf(out,"'"); + }else{ + break; } + z += i + 1; + } } /* @@ -12791,22 +12791,22 @@ static void output_html_string(FILE *out, const char *z){ ** array, then the string must be quoted for CSV. */ static const char needCsvQuote[] = { - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, }; /* @@ -12816,38 +12816,38 @@ static const char needCsvQuote[] = { ** is only issued if bSep is true. */ static void output_csv(ShellState *p, const char *z, int bSep){ - FILE *out = p->out; - if( z==0 ){ - utf8_printf(out,"%s",p->nullValue); + FILE *out = p->out; + if( z==0 ){ + utf8_printf(out,"%s",p->nullValue); + }else{ + unsigned i; + for(i=0; z[i]; i++){ + if( needCsvQuote[((unsigned char*)z)[i]] ){ + i = 0; + break; + } + } + if( i==0 || strstr(z, p->colSeparator)!=0 ){ + char *zQuoted = sqlite3_mprintf("\"%w\"", z); + utf8_printf(out, "%s", zQuoted); + sqlite3_free(zQuoted); }else{ - unsigned i; - for(i=0; z[i]; i++){ - if( needCsvQuote[((unsigned char*)z)[i]] ){ - i = 0; - break; - } - } - if( i==0 || strstr(z, p->colSeparator)!=0 ){ - char *zQuoted = sqlite3_mprintf("\"%w\"", z); - utf8_printf(out, "%s", zQuoted); - sqlite3_free(zQuoted); - }else{ - utf8_printf(out, "%s", z); - } - } - if( bSep ){ - utf8_printf(p->out, "%s", p->colSeparator); + utf8_printf(out, "%s", z); } + } + if( bSep ){ + utf8_printf(p->out, "%s", p->colSeparator); + } } /* ** This routine runs when the user presses Ctrl-C */ static void interrupt_handler(int NotUsed){ - UNUSED_PARAMETER(NotUsed); - seenInterrupt++; - if( seenInterrupt>2 ) exit(1); - if( globalDb ) sqlite3_interrupt(globalDb); + UNUSED_PARAMETER(NotUsed); + seenInterrupt++; + if( seenInterrupt>2 ) exit(1); + if( globalDb ) sqlite3_interrupt(globalDb); } #if (defined(_WIN32) || defined(WIN32)) && !defined(_WIN32_WCE) @@ -12855,13 +12855,13 @@ static void interrupt_handler(int NotUsed){ ** This routine runs for console events (e.g. Ctrl-C) on Win32 */ static BOOL WINAPI ConsoleCtrlHandler( - DWORD dwCtrlType /* One of the CTRL_*_EVENT constants */ + DWORD dwCtrlType /* One of the CTRL_*_EVENT constants */ ){ - if( dwCtrlType==CTRL_C_EVENT ){ - interrupt_handler(0); - return TRUE; - } - return FALSE; + if( dwCtrlType==CTRL_C_EVENT ){ + interrupt_handler(0); + return TRUE; + } + return FALSE; } #endif @@ -12870,43 +12870,43 @@ static BOOL WINAPI ConsoleCtrlHandler( ** This authorizer runs in safe mode. */ static int safeModeAuth( - void *pClientData, - int op, - const char *zA1, - const char *zA2, - const char *zA3, - const char *zA4 + void *pClientData, + int op, + const char *zA1, + const char *zA2, + const char *zA3, + const char *zA4 ){ - ShellState *p = (ShellState*)pClientData; - static const char *azProhibitedFunctions[] = { - "edit", - "fts3_tokenizer", - "load_extension", - "readfile", - "writefile", - "zipfile", - "zipfile_cds", - }; - UNUSED_PARAMETER(zA1); - UNUSED_PARAMETER(zA3); - UNUSED_PARAMETER(zA4); - switch( op ){ - case SQLITE_ATTACH: { - failIfSafeMode(p, "cannot run ATTACH in safe mode"); - break; - } - case SQLITE_FUNCTION: { - int i; - for(i=0; iout, "authorizer: %s", azAction[op]); - for(i=0; i<4; i++){ - raw_printf(p->out, " "); - if( az[i] ){ - output_c_string(p->out, az[i]); - }else{ - raw_printf(p->out, "NULL"); - } + ShellState *p = (ShellState*)pClientData; + static const char *azAction[] = { 0, + "CREATE_INDEX", "CREATE_TABLE", "CREATE_TEMP_INDEX", + "CREATE_TEMP_TABLE", "CREATE_TEMP_TRIGGER", "CREATE_TEMP_VIEW", + "CREATE_TRIGGER", "CREATE_VIEW", "DELETE", + "DROP_INDEX", "DROP_TABLE", "DROP_TEMP_INDEX", + "DROP_TEMP_TABLE", "DROP_TEMP_TRIGGER", "DROP_TEMP_VIEW", + "DROP_TRIGGER", "DROP_VIEW", "INSERT", + "PRAGMA", "READ", "SELECT", + "TRANSACTION", "UPDATE", "ATTACH", + "DETACH", "ALTER_TABLE", "REINDEX", + "ANALYZE", "CREATE_VTABLE", "DROP_VTABLE", + "FUNCTION", "SAVEPOINT", "RECURSIVE" + }; + int i; + const char *az[4]; + az[0] = zA1; + az[1] = zA2; + az[2] = zA3; + az[3] = zA4; + utf8_printf(p->out, "authorizer: %s", azAction[op]); + for(i=0; i<4; i++){ + raw_printf(p->out, " "); + if( az[i] ){ + output_c_string(p->out, az[i]); + }else{ + raw_printf(p->out, "NULL"); } - raw_printf(p->out, "\n"); - if( p->bSafeMode ) (void)safeModeAuth(pClientData, op, zA1, zA2, zA3, zA4); - return SQLITE_OK; + } + raw_printf(p->out, "\n"); + if( p->bSafeMode ) (void)safeModeAuth(pClientData, op, zA1, zA2, zA3, zA4); + return SQLITE_OK; } #endif @@ -12963,19 +12963,19 @@ static int shellAuth( ** in FTS3/4/5 into CREATE TABLE IF NOT EXISTS statements. */ static void printSchemaLine(FILE *out, const char *z, const char *zTail){ - if( z==0 ) return; - if( zTail==0 ) return; - if( sqlite3_strglob("CREATE TABLE ['\"]*", z)==0 ){ - utf8_printf(out, "CREATE TABLE IF NOT EXISTS %s%s", z+13, zTail); - }else{ - utf8_printf(out, "%s%s", z, zTail); - } + if( z==0 ) return; + if( zTail==0 ) return; + if( sqlite3_strglob("CREATE TABLE ['\"]*", z)==0 ){ + utf8_printf(out, "CREATE TABLE IF NOT EXISTS %s%s", z+13, zTail); + }else{ + utf8_printf(out, "%s%s", z, zTail); + } } static void printSchemaLineN(FILE *out, char *z, int n, const char *zTail){ - char c = z[n]; - z[n] = 0; - printSchemaLine(out, z, zTail); - z[n] = c; + char c = z[n]; + z[n] = 0; + printSchemaLine(out, z, zTail); + z[n] = c; } /* @@ -12983,37 +12983,37 @@ static void printSchemaLineN(FILE *out, char *z, int n, const char *zTail){ ** end of the first line. */ static int wsToEol(const char *z){ - int i; - for(i=0; z[i]; i++){ - if( z[i]=='\n' ) return 1; - if( IsSpace(z[i]) ) continue; - if( z[i]=='-' && z[i+1]=='-' ) return 1; - return 0; - } - return 1; + int i; + for(i=0; z[i]; i++){ + if( z[i]=='\n' ) return 1; + if( IsSpace(z[i]) ) continue; + if( z[i]=='-' && z[i+1]=='-' ) return 1; + return 0; + } + return 1; } /* ** Add a new entry to the EXPLAIN QUERY PLAN data */ static void eqp_append(ShellState *p, int iEqpId, int p2, const char *zText){ - EQPGraphRow *pNew; - int nText = strlen30(zText); - if( p->autoEQPtest ){ - utf8_printf(p->out, "%d,%d,%s\n", iEqpId, p2, zText); - } - pNew = sqlite3_malloc64( sizeof(*pNew) + nText ); - if( pNew==0 ) shell_out_of_memory(); - pNew->iEqpId = iEqpId; - pNew->iParentId = p2; - memcpy(pNew->zText, zText, nText+1); - pNew->pNext = 0; - if( p->sGraph.pLast ){ - p->sGraph.pLast->pNext = pNew; - }else{ - p->sGraph.pRow = pNew; - } - p->sGraph.pLast = pNew; + EQPGraphRow *pNew; + int nText = strlen30(zText); + if( p->autoEQPtest ){ + utf8_printf(p->out, "%d,%d,%s\n", iEqpId, p2, zText); + } + pNew = sqlite3_malloc64( sizeof(*pNew) + nText ); + if( pNew==0 ) shell_out_of_memory(); + pNew->iEqpId = iEqpId; + pNew->iParentId = p2; + memcpy(pNew->zText, zText, nText+1); + pNew->pNext = 0; + if( p->sGraph.pLast ){ + p->sGraph.pLast->pNext = pNew; + }else{ + p->sGraph.pRow = pNew; + } + p->sGraph.pLast = pNew; } /* @@ -13021,64 +13021,64 @@ static void eqp_append(ShellState *p, int iEqpId, int p2, const char *zText){ ** in p->sGraph. */ static void eqp_reset(ShellState *p){ - EQPGraphRow *pRow, *pNext; - for(pRow = p->sGraph.pRow; pRow; pRow = pNext){ - pNext = pRow->pNext; - sqlite3_free(pRow); - } - memset(&p->sGraph, 0, sizeof(p->sGraph)); + EQPGraphRow *pRow, *pNext; + for(pRow = p->sGraph.pRow; pRow; pRow = pNext){ + pNext = pRow->pNext; + sqlite3_free(pRow); + } + memset(&p->sGraph, 0, sizeof(p->sGraph)); } /* Return the next EXPLAIN QUERY PLAN line with iEqpId that occurs after ** pOld, or return the first such line if pOld is NULL */ static EQPGraphRow *eqp_next_row(ShellState *p, int iEqpId, EQPGraphRow *pOld){ - EQPGraphRow *pRow = pOld ? pOld->pNext : p->sGraph.pRow; - while( pRow && pRow->iParentId!=iEqpId ) pRow = pRow->pNext; - return pRow; + EQPGraphRow *pRow = pOld ? pOld->pNext : p->sGraph.pRow; + while( pRow && pRow->iParentId!=iEqpId ) pRow = pRow->pNext; + return pRow; } /* Render a single level of the graph that has iEqpId as its parent. Called ** recursively to render sublevels. */ static void eqp_render_level(ShellState *p, int iEqpId){ - EQPGraphRow *pRow, *pNext; - int n = strlen30(p->sGraph.zPrefix); - char *z; - for(pRow = eqp_next_row(p, iEqpId, 0); pRow; pRow = pNext){ - pNext = eqp_next_row(p, iEqpId, pRow); - z = pRow->zText; - utf8_printf(p->out, "%s%s%s\n", p->sGraph.zPrefix, - pNext ? "|--" : "`--", z); - if( n<(int)sizeof(p->sGraph.zPrefix)-7 ){ - memcpy(&p->sGraph.zPrefix[n], pNext ? "| " : " ", 4); - eqp_render_level(p, pRow->iEqpId); - p->sGraph.zPrefix[n] = 0; - } + EQPGraphRow *pRow, *pNext; + int n = strlen30(p->sGraph.zPrefix); + char *z; + for(pRow = eqp_next_row(p, iEqpId, 0); pRow; pRow = pNext){ + pNext = eqp_next_row(p, iEqpId, pRow); + z = pRow->zText; + utf8_printf(p->out, "%s%s%s\n", p->sGraph.zPrefix, + pNext ? "|--" : "`--", z); + if( n<(int)sizeof(p->sGraph.zPrefix)-7 ){ + memcpy(&p->sGraph.zPrefix[n], pNext ? "| " : " ", 4); + eqp_render_level(p, pRow->iEqpId); + p->sGraph.zPrefix[n] = 0; } + } } /* ** Display and reset the EXPLAIN QUERY PLAN data */ static void eqp_render(ShellState *p){ - EQPGraphRow *pRow = p->sGraph.pRow; - if( pRow ){ - if( pRow->zText[0]=='-' ){ - if( pRow->pNext==0 ){ - eqp_reset(p); - return; - } - utf8_printf(p->out, "%s\n", pRow->zText+3); - p->sGraph.pRow = pRow->pNext; - sqlite3_free(pRow); - }else{ - utf8_printf(p->out, "QUERY PLAN\n"); - } - p->sGraph.zPrefix[0] = 0; - eqp_render_level(p, 0); + EQPGraphRow *pRow = p->sGraph.pRow; + if( pRow ){ + if( pRow->zText[0]=='-' ){ + if( pRow->pNext==0 ){ eqp_reset(p); + return; + } + utf8_printf(p->out, "%s\n", pRow->zText+3); + p->sGraph.pRow = pRow->pNext; + sqlite3_free(pRow); + }else{ + utf8_printf(p->out, "QUERY PLAN\n"); } + p->sGraph.zPrefix[0] = 0; + eqp_render_level(p, 0); + eqp_reset(p); + } } #ifndef SQLITE_OMIT_PROGRESS_CALLBACK @@ -13086,18 +13086,18 @@ static void eqp_render(ShellState *p){ ** Progress handler callback. */ static int progress_handler(void *pClientData) { - ShellState *p = (ShellState*)pClientData; - p->nProgress++; - if( p->nProgress>=p->mxProgress && p->mxProgress>0 ){ - raw_printf(p->out, "Progress limit reached (%u)\n", p->nProgress); - if( p->flgProgress & SHELL_PROGRESS_RESET ) p->nProgress = 0; - if( p->flgProgress & SHELL_PROGRESS_ONCE ) p->mxProgress = 0; - return 1; - } - if( (p->flgProgress & SHELL_PROGRESS_QUIET)==0 ){ - raw_printf(p->out, "Progress %u\n", p->nProgress); - } - return 0; + ShellState *p = (ShellState*)pClientData; + p->nProgress++; + if( p->nProgress>=p->mxProgress && p->mxProgress>0 ){ + raw_printf(p->out, "Progress limit reached (%u)\n", p->nProgress); + if( p->flgProgress & SHELL_PROGRESS_RESET ) p->nProgress = 0; + if( p->flgProgress & SHELL_PROGRESS_ONCE ) p->mxProgress = 0; + return 1; + } + if( (p->flgProgress & SHELL_PROGRESS_QUIET)==0 ){ + raw_printf(p->out, "Progress %u\n", p->nProgress); + } + return 0; } #endif /* SQLITE_OMIT_PROGRESS_CALLBACK */ @@ -13105,34 +13105,34 @@ static int progress_handler(void *pClientData) { ** Print N dashes */ static void print_dashes(FILE *out, int N){ - const char zDash[] = "--------------------------------------------------"; - const int nDash = sizeof(zDash) - 1; - while( N>nDash ){ - fputs(zDash, out); - N -= nDash; - } - raw_printf(out, "%.*s", N, zDash); + const char zDash[] = "--------------------------------------------------"; + const int nDash = sizeof(zDash) - 1; + while( N>nDash ){ + fputs(zDash, out); + N -= nDash; + } + raw_printf(out, "%.*s", N, zDash); } /* ** Print a markdown or table-style row separator using ascii-art */ static void print_row_separator( - ShellState *p, - int nArg, - const char *zSep + ShellState *p, + int nArg, + const char *zSep ){ - int i; - if( nArg>0 ){ - fputs(zSep, p->out); - print_dashes(p->out, p->actualWidth[0]+2); - for(i=1; iout); - print_dashes(p->out, p->actualWidth[i]+2); - } - fputs(zSep, p->out); + int i; + if( nArg>0 ){ + fputs(zSep, p->out); + print_dashes(p->out, p->actualWidth[0]+2); + for(i=1; iout); + print_dashes(p->out, p->actualWidth[i]+2); } - fputs("\n", p->out); + fputs(zSep, p->out); + } + fputs("\n", p->out); } /* @@ -13140,366 +13140,366 @@ static void print_row_separator( ** invokes for each row of a query result. */ static int shell_callback( - void *pArg, - int nArg, /* Number of result columns */ - char **azArg, /* Text of each result column */ - char **azCol, /* Column names */ - int *aiType /* Column types. Might be NULL */ + void *pArg, + int nArg, /* Number of result columns */ + char **azArg, /* Text of each result column */ + char **azCol, /* Column names */ + int *aiType /* Column types. Might be NULL */ ){ - int i; - ShellState *p = (ShellState*)pArg; - - if( azArg==0 ) return 0; - switch( p->cMode ){ - case MODE_Line: { - int w = 5; - if( azArg==0 ) break; - for(i=0; iw ) w = len; - } - if( p->cnt++>0 ) utf8_printf(p->out, "%s", p->rowSeparator); - for(i=0; iout,"%*s = %s%s", w, azCol[i], - azArg[i] ? azArg[i] : p->nullValue, p->rowSeparator); - } - break; - } - case MODE_Explain: { - static const int aExplainWidth[] = {4, 13, 4, 4, 4, 13, 2, 13}; - if( nArg>ArraySize(aExplainWidth) ){ - nArg = ArraySize(aExplainWidth); - } - if( p->cnt++==0 ){ - for(i=0; iout, w, azCol[i]); - fputs(i==nArg-1 ? "\n" : " ", p->out); - } - for(i=0; iout, w); - fputs(i==nArg-1 ? "\n" : " ", p->out); - } - } - if( azArg==0 ) break; - for(i=0; iw ){ - w = strlenChar(azArg[i]); - } - if( i==1 && p->aiIndent && p->pStmt ){ - if( p->iIndentnIndent ){ - utf8_printf(p->out, "%*.s", p->aiIndent[p->iIndent], ""); - } - p->iIndent++; - } - utf8_width_print(p->out, w, azArg[i] ? azArg[i] : p->nullValue); - fputs(i==nArg-1 ? "\n" : " ", p->out); - } - break; - } - case MODE_Semi: { /* .schema and .fullschema output */ - printSchemaLine(p->out, azArg[0], ";\n"); - break; - } - case MODE_Pretty: { /* .schema and .fullschema with --indent */ - char *z; - int j; - int nParen = 0; - char cEnd = 0; - char c; - int nLine = 0; - assert( nArg==1 ); - if( azArg[0]==0 ) break; - if( sqlite3_strlike("CREATE VIEW%", azArg[0], 0)==0 - || sqlite3_strlike("CREATE TRIG%", azArg[0], 0)==0 - ){ - utf8_printf(p->out, "%s;\n", azArg[0]); - break; - } - z = sqlite3_mprintf("%s", azArg[0]); + int i; + ShellState *p = (ShellState*)pArg; + + if( azArg==0 ) return 0; + switch( p->cMode ){ + case MODE_Line: { + int w = 5; + if( azArg==0 ) break; + for(i=0; iw ) w = len; + } + if( p->cnt++>0 ) utf8_printf(p->out, "%s", p->rowSeparator); + for(i=0; iout,"%*s = %s%s", w, azCol[i], + azArg[i] ? azArg[i] : p->nullValue, p->rowSeparator); + } + break; + } + case MODE_Explain: { + static const int aExplainWidth[] = {4, 13, 4, 4, 4, 13, 2, 13}; + if( nArg>ArraySize(aExplainWidth) ){ + nArg = ArraySize(aExplainWidth); + } + if( p->cnt++==0 ){ + for(i=0; iout, w, azCol[i]); + fputs(i==nArg-1 ? "\n" : " ", p->out); + } + for(i=0; iout, w); + fputs(i==nArg-1 ? "\n" : " ", p->out); + } + } + if( azArg==0 ) break; + for(i=0; iw ){ + w = strlenChar(azArg[i]); + } + if( i==1 && p->aiIndent && p->pStmt ){ + if( p->iIndentnIndent ){ + utf8_printf(p->out, "%*.s", p->aiIndent[p->iIndent], ""); + } + p->iIndent++; + } + utf8_width_print(p->out, w, azArg[i] ? azArg[i] : p->nullValue); + fputs(i==nArg-1 ? "\n" : " ", p->out); + } + break; + } + case MODE_Semi: { /* .schema and .fullschema output */ + printSchemaLine(p->out, azArg[0], ";\n"); + break; + } + case MODE_Pretty: { /* .schema and .fullschema with --indent */ + char *z; + int j; + int nParen = 0; + char cEnd = 0; + char c; + int nLine = 0; + assert( nArg==1 ); + if( azArg[0]==0 ) break; + if( sqlite3_strlike("CREATE VIEW%", azArg[0], 0)==0 + || sqlite3_strlike("CREATE TRIG%", azArg[0], 0)==0 + ){ + utf8_printf(p->out, "%s;\n", azArg[0]); + break; + } + z = sqlite3_mprintf("%s", azArg[0]); + j = 0; + for(i=0; IsSpace(z[i]); i++){} + for(; (c = z[i])!=0; i++){ + if( IsSpace(c) ){ + if( z[j-1]=='\r' ) z[j-1] = '\n'; + if( IsSpace(z[j-1]) || z[j-1]=='(' ) continue; + }else if( (c=='(' || c==')') && j>0 && IsSpace(z[j-1]) ){ + j--; + } + z[j++] = c; + } + while( j>0 && IsSpace(z[j-1]) ){ j--; } + z[j] = 0; + if( strlen30(z)>=79 ){ + for(i=j=0; (c = z[i])!=0; i++){ /* Copy from z[i] back to z[j] */ + if( c==cEnd ){ + cEnd = 0; + }else if( c=='"' || c=='\'' || c=='`' ){ + cEnd = c; + }else if( c=='[' ){ + cEnd = ']'; + }else if( c=='-' && z[i+1]=='-' ){ + cEnd = '\n'; + }else if( c=='(' ){ + nParen++; + }else if( c==')' ){ + nParen--; + if( nLine>0 && nParen==0 && j>0 ){ + printSchemaLineN(p->out, z, j, "\n"); + j = 0; + } + } + z[j++] = c; + if( nParen==1 && cEnd==0 + && (c=='(' || c=='\n' || (c==',' && !wsToEol(z+i+1))) + ){ + if( c=='\n' ) j--; + printSchemaLineN(p->out, z, j, "\n "); j = 0; - for(i=0; IsSpace(z[i]); i++){} - for(; (c = z[i])!=0; i++){ - if( IsSpace(c) ){ - if( z[j-1]=='\r' ) z[j-1] = '\n'; - if( IsSpace(z[j-1]) || z[j-1]=='(' ) continue; - }else if( (c=='(' || c==')') && j>0 && IsSpace(z[j-1]) ){ - j--; - } - z[j++] = c; - } - while( j>0 && IsSpace(z[j-1]) ){ j--; } - z[j] = 0; - if( strlen30(z)>=79 ){ - for(i=j=0; (c = z[i])!=0; i++){ /* Copy from z[i] back to z[j] */ - if( c==cEnd ){ - cEnd = 0; - }else if( c=='"' || c=='\'' || c=='`' ){ - cEnd = c; - }else if( c=='[' ){ - cEnd = ']'; - }else if( c=='-' && z[i+1]=='-' ){ - cEnd = '\n'; - }else if( c=='(' ){ - nParen++; - }else if( c==')' ){ - nParen--; - if( nLine>0 && nParen==0 && j>0 ){ - printSchemaLineN(p->out, z, j, "\n"); - j = 0; - } - } - z[j++] = c; - if( nParen==1 && cEnd==0 - && (c=='(' || c=='\n' || (c==',' && !wsToEol(z+i+1))) - ){ - if( c=='\n' ) j--; - printSchemaLineN(p->out, z, j, "\n "); - j = 0; - nLine++; - while( IsSpace(z[i+1]) ){ i++; } - } - } - z[j] = 0; - } - printSchemaLine(p->out, z, ";\n"); + nLine++; + while( IsSpace(z[i+1]) ){ i++; } + } + } + z[j] = 0; + } + printSchemaLine(p->out, z, ";\n"); + sqlite3_free(z); + break; + } + case MODE_List: { + if( p->cnt++==0 && p->showHeader ){ + for(i=0; iout,"%s%s",azCol[i], + i==nArg-1 ? p->rowSeparator : p->colSeparator); + } + } + if( azArg==0 ) break; + for(i=0; inullValue; + utf8_printf(p->out, "%s", z); + if( iout, "%s", p->colSeparator); + }else{ + utf8_printf(p->out, "%s", p->rowSeparator); + } + } + break; + } + case MODE_Html: { + if( p->cnt++==0 && p->showHeader ){ + raw_printf(p->out,""); + for(i=0; iout,"\n"); + } + raw_printf(p->out,"\n"); + } + if( azArg==0 ) break; + raw_printf(p->out,""); + for(i=0; iout,"\n"); + } + raw_printf(p->out,"\n"); + break; + } + case MODE_Tcl: { + if( p->cnt++==0 && p->showHeader ){ + for(i=0; iout,azCol[i] ? azCol[i] : ""); + if(iout, "%s", p->colSeparator); + } + utf8_printf(p->out, "%s", p->rowSeparator); + } + if( azArg==0 ) break; + for(i=0; iout, azArg[i] ? azArg[i] : p->nullValue); + if(iout, "%s", p->colSeparator); + } + utf8_printf(p->out, "%s", p->rowSeparator); + break; + } + case MODE_Csv: { + setBinaryMode(p->out, 1); + if( p->cnt++==0 && p->showHeader ){ + for(i=0; iout, "%s", p->rowSeparator); + } + if( nArg>0 ){ + for(i=0; iout, "%s", p->rowSeparator); + } + setTextMode(p->out, 1); + break; + } + case MODE_Insert: { + if( azArg==0 ) break; + utf8_printf(p->out,"INSERT INTO %s",p->zDestTable); + if( p->showHeader ){ + raw_printf(p->out,"("); + for(i=0; i0 ) raw_printf(p->out, ","); + if( quoteChar(azCol[i]) ){ + char *z = sqlite3_mprintf("\"%w\"", azCol[i]); + utf8_printf(p->out, "%s", z); sqlite3_free(z); - break; - } - case MODE_List: { - if( p->cnt++==0 && p->showHeader ){ - for(i=0; iout,"%s%s",azCol[i], - i==nArg-1 ? p->rowSeparator : p->colSeparator); - } - } - if( azArg==0 ) break; - for(i=0; inullValue; - utf8_printf(p->out, "%s", z); - if( iout, "%s", p->colSeparator); - }else{ - utf8_printf(p->out, "%s", p->rowSeparator); - } - } - break; - } - case MODE_Html: { - if( p->cnt++==0 && p->showHeader ){ - raw_printf(p->out,""); - for(i=0; iout,"\n"); - } - raw_printf(p->out,"\n"); - } - if( azArg==0 ) break; - raw_printf(p->out,""); - for(i=0; iout,"\n"); - } - raw_printf(p->out,"\n"); - break; - } - case MODE_Tcl: { - if( p->cnt++==0 && p->showHeader ){ - for(i=0; iout,azCol[i] ? azCol[i] : ""); - if(iout, "%s", p->colSeparator); - } - utf8_printf(p->out, "%s", p->rowSeparator); - } - if( azArg==0 ) break; - for(i=0; iout, azArg[i] ? azArg[i] : p->nullValue); - if(iout, "%s", p->colSeparator); - } - utf8_printf(p->out, "%s", p->rowSeparator); - break; - } - case MODE_Csv: { - setBinaryMode(p->out, 1); - if( p->cnt++==0 && p->showHeader ){ - for(i=0; iout, "%s", p->rowSeparator); - } - if( nArg>0 ){ - for(i=0; iout, "%s", p->rowSeparator); - } - setTextMode(p->out, 1); - break; - } - case MODE_Insert: { - if( azArg==0 ) break; - utf8_printf(p->out,"INSERT INTO %s",p->zDestTable); - if( p->showHeader ){ - raw_printf(p->out,"("); - for(i=0; i0 ) raw_printf(p->out, ","); - if( quoteChar(azCol[i]) ){ - char *z = sqlite3_mprintf("\"%w\"", azCol[i]); - utf8_printf(p->out, "%s", z); - sqlite3_free(z); - }else{ - raw_printf(p->out, "%s", azCol[i]); - } - } - raw_printf(p->out,")"); - } - p->cnt++; - for(i=0; iout, i>0 ? "," : " VALUES("); - if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){ - utf8_printf(p->out,"NULL"); - }else if( aiType && aiType[i]==SQLITE_TEXT ){ - if( ShellHasFlag(p, SHFLG_Newlines) ){ - output_quoted_string(p->out, azArg[i]); - }else{ - output_quoted_escaped_string(p->out, azArg[i]); - } - }else if( aiType && aiType[i]==SQLITE_INTEGER ){ - utf8_printf(p->out,"%s", azArg[i]); - }else if( aiType && aiType[i]==SQLITE_FLOAT ){ - char z[50]; - double r = sqlite3_column_double(p->pStmt, i); - sqlite3_uint64 ur; - memcpy(&ur,&r,sizeof(r)); - if( ur==0x7ff0000000000000LL ){ - raw_printf(p->out, "1e999"); - }else if( ur==0xfff0000000000000LL ){ - raw_printf(p->out, "-1e999"); - }else{ - sqlite3_snprintf(50,z,"%!.20g", r); - raw_printf(p->out, "%s", z); - } - }else if( aiType && aiType[i]==SQLITE_BLOB && p->pStmt ){ - const void *pBlob = sqlite3_column_blob(p->pStmt, i); - int nBlob = sqlite3_column_bytes(p->pStmt, i); - output_hex_blob(p->out, pBlob, nBlob); - }else if( isNumber(azArg[i], 0) ){ - utf8_printf(p->out,"%s", azArg[i]); - }else if( ShellHasFlag(p, SHFLG_Newlines) ){ - output_quoted_string(p->out, azArg[i]); - }else{ - output_quoted_escaped_string(p->out, azArg[i]); - } - } - raw_printf(p->out,");\n"); - break; - } - case MODE_Json: { - if( azArg==0 ) break; - if( p->cnt==0 ){ - fputs("[{", p->out); - }else{ - fputs(",\n{", p->out); - } - p->cnt++; - for(i=0; iout, azCol[i], -1); - putc(':', p->out); - if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){ - fputs("null",p->out); - }else if( aiType && aiType[i]==SQLITE_FLOAT ){ - char z[50]; - double r = sqlite3_column_double(p->pStmt, i); - sqlite3_uint64 ur; - memcpy(&ur,&r,sizeof(r)); - if( ur==0x7ff0000000000000LL ){ - raw_printf(p->out, "1e999"); - }else if( ur==0xfff0000000000000LL ){ - raw_printf(p->out, "-1e999"); - }else{ - sqlite3_snprintf(50,z,"%!.20g", r); - raw_printf(p->out, "%s", z); - } - }else if( aiType && aiType[i]==SQLITE_BLOB && p->pStmt ){ - const void *pBlob = sqlite3_column_blob(p->pStmt, i); - int nBlob = sqlite3_column_bytes(p->pStmt, i); - output_json_string(p->out, pBlob, nBlob); - }else if( aiType && aiType[i]==SQLITE_TEXT ){ - output_json_string(p->out, azArg[i], -1); - }else{ - utf8_printf(p->out,"%s", azArg[i]); - } - if( iout); - } - } - putc('}', p->out); - break; - } - case MODE_Quote: { - if( azArg==0 ) break; - if( p->cnt==0 && p->showHeader ){ - for(i=0; i0 ) fputs(p->colSeparator, p->out); - output_quoted_string(p->out, azCol[i]); - } - fputs(p->rowSeparator, p->out); - } - p->cnt++; - for(i=0; i0 ) fputs(p->colSeparator, p->out); - if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){ - utf8_printf(p->out,"NULL"); - }else if( aiType && aiType[i]==SQLITE_TEXT ){ - output_quoted_string(p->out, azArg[i]); - }else if( aiType && aiType[i]==SQLITE_INTEGER ){ - utf8_printf(p->out,"%s", azArg[i]); - }else if( aiType && aiType[i]==SQLITE_FLOAT ){ - char z[50]; - double r = sqlite3_column_double(p->pStmt, i); - sqlite3_snprintf(50,z,"%!.20g", r); - raw_printf(p->out, "%s", z); - }else if( aiType && aiType[i]==SQLITE_BLOB && p->pStmt ){ - const void *pBlob = sqlite3_column_blob(p->pStmt, i); - int nBlob = sqlite3_column_bytes(p->pStmt, i); - output_hex_blob(p->out, pBlob, nBlob); - }else if( isNumber(azArg[i], 0) ){ - utf8_printf(p->out,"%s", azArg[i]); - }else{ - output_quoted_string(p->out, azArg[i]); - } - } - fputs(p->rowSeparator, p->out); - break; - } - case MODE_Ascii: { - if( p->cnt++==0 && p->showHeader ){ - for(i=0; i0 ) utf8_printf(p->out, "%s", p->colSeparator); - utf8_printf(p->out,"%s",azCol[i] ? azCol[i] : ""); - } - utf8_printf(p->out, "%s", p->rowSeparator); - } - if( azArg==0 ) break; - for(i=0; i0 ) utf8_printf(p->out, "%s", p->colSeparator); - utf8_printf(p->out,"%s",azArg[i] ? azArg[i] : p->nullValue); - } - utf8_printf(p->out, "%s", p->rowSeparator); - break; + }else{ + raw_printf(p->out, "%s", azCol[i]); + } + } + raw_printf(p->out,")"); + } + p->cnt++; + for(i=0; iout, i>0 ? "," : " VALUES("); + if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){ + utf8_printf(p->out,"NULL"); + }else if( aiType && aiType[i]==SQLITE_TEXT ){ + if( ShellHasFlag(p, SHFLG_Newlines) ){ + output_quoted_string(p->out, azArg[i]); + }else{ + output_quoted_escaped_string(p->out, azArg[i]); + } + }else if( aiType && aiType[i]==SQLITE_INTEGER ){ + utf8_printf(p->out,"%s", azArg[i]); + }else if( aiType && aiType[i]==SQLITE_FLOAT ){ + char z[50]; + double r = sqlite3_column_double(p->pStmt, i); + sqlite3_uint64 ur; + memcpy(&ur,&r,sizeof(r)); + if( ur==0x7ff0000000000000LL ){ + raw_printf(p->out, "1e999"); + }else if( ur==0xfff0000000000000LL ){ + raw_printf(p->out, "-1e999"); + }else{ + sqlite3_snprintf(50,z,"%!.20g", r); + raw_printf(p->out, "%s", z); + } + }else if( aiType && aiType[i]==SQLITE_BLOB && p->pStmt ){ + const void *pBlob = sqlite3_column_blob(p->pStmt, i); + int nBlob = sqlite3_column_bytes(p->pStmt, i); + output_hex_blob(p->out, pBlob, nBlob); + }else if( isNumber(azArg[i], 0) ){ + utf8_printf(p->out,"%s", azArg[i]); + }else if( ShellHasFlag(p, SHFLG_Newlines) ){ + output_quoted_string(p->out, azArg[i]); + }else{ + output_quoted_escaped_string(p->out, azArg[i]); + } + } + raw_printf(p->out,");\n"); + break; + } + case MODE_Json: { + if( azArg==0 ) break; + if( p->cnt==0 ){ + fputs("[{", p->out); + }else{ + fputs(",\n{", p->out); + } + p->cnt++; + for(i=0; iout, azCol[i], -1); + putc(':', p->out); + if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){ + fputs("null",p->out); + }else if( aiType && aiType[i]==SQLITE_FLOAT ){ + char z[50]; + double r = sqlite3_column_double(p->pStmt, i); + sqlite3_uint64 ur; + memcpy(&ur,&r,sizeof(r)); + if( ur==0x7ff0000000000000LL ){ + raw_printf(p->out, "1e999"); + }else if( ur==0xfff0000000000000LL ){ + raw_printf(p->out, "-1e999"); + }else{ + sqlite3_snprintf(50,z,"%!.20g", r); + raw_printf(p->out, "%s", z); + } + }else if( aiType && aiType[i]==SQLITE_BLOB && p->pStmt ){ + const void *pBlob = sqlite3_column_blob(p->pStmt, i); + int nBlob = sqlite3_column_bytes(p->pStmt, i); + output_json_string(p->out, pBlob, nBlob); + }else if( aiType && aiType[i]==SQLITE_TEXT ){ + output_json_string(p->out, azArg[i], -1); + }else{ + utf8_printf(p->out,"%s", azArg[i]); + } + if( iout); + } + } + putc('}', p->out); + break; + } + case MODE_Quote: { + if( azArg==0 ) break; + if( p->cnt==0 && p->showHeader ){ + for(i=0; i0 ) fputs(p->colSeparator, p->out); + output_quoted_string(p->out, azCol[i]); + } + fputs(p->rowSeparator, p->out); + } + p->cnt++; + for(i=0; i0 ) fputs(p->colSeparator, p->out); + if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){ + utf8_printf(p->out,"NULL"); + }else if( aiType && aiType[i]==SQLITE_TEXT ){ + output_quoted_string(p->out, azArg[i]); + }else if( aiType && aiType[i]==SQLITE_INTEGER ){ + utf8_printf(p->out,"%s", azArg[i]); + }else if( aiType && aiType[i]==SQLITE_FLOAT ){ + char z[50]; + double r = sqlite3_column_double(p->pStmt, i); + sqlite3_snprintf(50,z,"%!.20g", r); + raw_printf(p->out, "%s", z); + }else if( aiType && aiType[i]==SQLITE_BLOB && p->pStmt ){ + const void *pBlob = sqlite3_column_blob(p->pStmt, i); + int nBlob = sqlite3_column_bytes(p->pStmt, i); + output_hex_blob(p->out, pBlob, nBlob); + }else if( isNumber(azArg[i], 0) ){ + utf8_printf(p->out,"%s", azArg[i]); + }else{ + output_quoted_string(p->out, azArg[i]); } - case MODE_EQP: { - eqp_append(p, atoi(azArg[0]), atoi(azArg[1]), azArg[3]); - break; + } + fputs(p->rowSeparator, p->out); + break; + } + case MODE_Ascii: { + if( p->cnt++==0 && p->showHeader ){ + for(i=0; i0 ) utf8_printf(p->out, "%s", p->colSeparator); + utf8_printf(p->out,"%s",azCol[i] ? azCol[i] : ""); } + utf8_printf(p->out, "%s", p->rowSeparator); + } + if( azArg==0 ) break; + for(i=0; i0 ) utf8_printf(p->out, "%s", p->colSeparator); + utf8_printf(p->out,"%s",azArg[i] ? azArg[i] : p->nullValue); + } + utf8_printf(p->out, "%s", p->rowSeparator); + break; } - return 0; + case MODE_EQP: { + eqp_append(p, atoi(azArg[0]), atoi(azArg[1]), azArg[3]); + break; + } + } + return 0; } /* @@ -13507,8 +13507,8 @@ static int shell_callback( ** invokes for each row of a query result. */ static int callback(void *pArg, int nArg, char **azArg, char **azCol){ - /* since we don't have type info, call the shell_callback with a NULL value */ - return shell_callback(pArg, nArg, azArg, azCol, NULL); + /* since we don't have type info, call the shell_callback with a NULL value */ + return shell_callback(pArg, nArg, azArg, azCol, NULL); } /* @@ -13516,64 +13516,64 @@ static int callback(void *pArg, int nArg, char **azArg, char **azCol){ ** output onto the end of a ShellText object. */ static int captureOutputCallback(void *pArg, int nArg, char **azArg, char **az){ - ShellText *p = (ShellText*)pArg; - int i; - UNUSED_PARAMETER(az); - if( azArg==0 ) return 0; - if( p->n ) appendText(p, "|", 0); - for(i=0; in ) appendText(p, "|", 0); + for(i=0; idb, - "SAVEPOINT selftest_init;\n" - "CREATE TABLE IF NOT EXISTS selftest(\n" - " tno INTEGER PRIMARY KEY,\n" /* Test number */ - " op TEXT,\n" /* Operator: memo run */ - " cmd TEXT,\n" /* Command text */ - " ans TEXT\n" /* Desired answer */ - ");" - "CREATE TEMP TABLE [_shell$self](op,cmd,ans);\n" - "INSERT INTO [_shell$self](rowid,op,cmd)\n" - " VALUES(coalesce((SELECT (max(tno)+100)/10 FROM selftest),10),\n" - " 'memo','Tests generated by --init');\n" - "INSERT INTO [_shell$self]\n" - " SELECT 'run',\n" - " 'SELECT hex(sha3_query(''SELECT type,name,tbl_name,sql " - "FROM sqlite_schema ORDER BY 2'',224))',\n" - " hex(sha3_query('SELECT type,name,tbl_name,sql " - "FROM sqlite_schema ORDER BY 2',224));\n" - "INSERT INTO [_shell$self]\n" - " SELECT 'run'," - " 'SELECT hex(sha3_query(''SELECT * FROM \"' ||" - " printf('%w',name) || '\" NOT INDEXED'',224))',\n" - " hex(sha3_query(printf('SELECT * FROM \"%w\" NOT INDEXED',name),224))\n" - " FROM (\n" - " SELECT name FROM sqlite_schema\n" - " WHERE type='table'\n" - " AND name<>'selftest'\n" - " AND coalesce(rootpage,0)>0\n" - " )\n" - " ORDER BY name;\n" - "INSERT INTO [_shell$self]\n" - " VALUES('run','PRAGMA integrity_check','ok');\n" - "INSERT INTO selftest(tno,op,cmd,ans)" - " SELECT rowid*10,op,cmd,ans FROM [_shell$self];\n" - "DROP TABLE [_shell$self];" - ,0,0,&zErrMsg); - if( zErrMsg ){ - utf8_printf(stderr, "SELFTEST initialization failure: %s\n", zErrMsg); - sqlite3_free(zErrMsg); - } - sqlite3_exec(p->db, "RELEASE selftest_init",0,0,0); + char *zErrMsg = 0; + sqlite3_exec(p->db, + "SAVEPOINT selftest_init;\n" + "CREATE TABLE IF NOT EXISTS selftest(\n" + " tno INTEGER PRIMARY KEY,\n" /* Test number */ + " op TEXT,\n" /* Operator: memo run */ + " cmd TEXT,\n" /* Command text */ + " ans TEXT\n" /* Desired answer */ + ");" + "CREATE TEMP TABLE [_shell$self](op,cmd,ans);\n" + "INSERT INTO [_shell$self](rowid,op,cmd)\n" + " VALUES(coalesce((SELECT (max(tno)+100)/10 FROM selftest),10),\n" + " 'memo','Tests generated by --init');\n" + "INSERT INTO [_shell$self]\n" + " SELECT 'run',\n" + " 'SELECT hex(sha3_query(''SELECT type,name,tbl_name,sql " + "FROM sqlite_schema ORDER BY 2'',224))',\n" + " hex(sha3_query('SELECT type,name,tbl_name,sql " + "FROM sqlite_schema ORDER BY 2',224));\n" + "INSERT INTO [_shell$self]\n" + " SELECT 'run'," + " 'SELECT hex(sha3_query(''SELECT * FROM \"' ||" + " printf('%w',name) || '\" NOT INDEXED'',224))',\n" + " hex(sha3_query(printf('SELECT * FROM \"%w\" NOT INDEXED',name),224))\n" + " FROM (\n" + " SELECT name FROM sqlite_schema\n" + " WHERE type='table'\n" + " AND name<>'selftest'\n" + " AND coalesce(rootpage,0)>0\n" + " )\n" + " ORDER BY name;\n" + "INSERT INTO [_shell$self]\n" + " VALUES('run','PRAGMA integrity_check','ok');\n" + "INSERT INTO selftest(tno,op,cmd,ans)" + " SELECT rowid*10,op,cmd,ans FROM [_shell$self];\n" + "DROP TABLE [_shell$self];" + ,0,0,&zErrMsg); + if( zErrMsg ){ + utf8_printf(stderr, "SELFTEST initialization failure: %s\n", zErrMsg); + sqlite3_free(zErrMsg); + } + sqlite3_exec(p->db, "RELEASE selftest_init",0,0,0); } @@ -13583,28 +13583,28 @@ static void createSelftestTable(ShellState *p){ ** table name. */ static void set_table_name(ShellState *p, const char *zName){ - int i, n; - char cQuote; - char *z; - - if( p->zDestTable ){ - free(p->zDestTable); - p->zDestTable = 0; - } - if( zName==0 ) return; - cQuote = quoteChar(zName); - n = strlen30(zName); - if( cQuote ) n += n+2; - z = p->zDestTable = malloc( n+1 ); - if( z==0 ) shell_out_of_memory(); - n = 0; - if( cQuote ) z[n++] = cQuote; - for(i=0; zName[i]; i++){ - z[n++] = zName[i]; - if( zName[i]==cQuote ) z[n++] = cQuote; - } - if( cQuote ) z[n++] = cQuote; - z[n] = 0; + int i, n; + char cQuote; + char *z; + + if( p->zDestTable ){ + free(p->zDestTable); + p->zDestTable = 0; + } + if( zName==0 ) return; + cQuote = quoteChar(zName); + n = strlen30(zName); + if( cQuote ) n += n+2; + z = p->zDestTable = malloc( n+1 ); + if( z==0 ) shell_out_of_memory(); + n = 0; + if( cQuote ) z[n++] = cQuote; + for(i=0; zName[i]; i++){ + z[n++] = zName[i]; + if( zName[i]==cQuote ) z[n++] = cQuote; + } + if( cQuote ) z[n++] = cQuote; + z[n] = 0; } @@ -13619,58 +13619,58 @@ static void set_table_name(ShellState *p, const char *zName){ ** won't consume the semicolon terminator. */ static int run_table_dump_query( - ShellState *p, /* Query context */ - const char *zSelect /* SELECT statement to extract content */ + ShellState *p, /* Query context */ + const char *zSelect /* SELECT statement to extract content */ ){ - sqlite3_stmt *pSelect; - int rc; - int nResult; - int i; - const char *z; - rc = sqlite3_prepare_v2(p->db, zSelect, -1, &pSelect, 0); - if( rc!=SQLITE_OK || !pSelect ){ - utf8_printf(p->out, "/**** ERROR: (%d) %s *****/\n", rc, - sqlite3_errmsg(p->db)); - if( (rc&0xff)!=SQLITE_CORRUPT ) p->nErr++; - return rc; + sqlite3_stmt *pSelect; + int rc; + int nResult; + int i; + const char *z; + rc = sqlite3_prepare_v2(p->db, zSelect, -1, &pSelect, 0); + if( rc!=SQLITE_OK || !pSelect ){ + utf8_printf(p->out, "/**** ERROR: (%d) %s *****/\n", rc, + sqlite3_errmsg(p->db)); + if( (rc&0xff)!=SQLITE_CORRUPT ) p->nErr++; + return rc; + } + rc = sqlite3_step(pSelect); + nResult = sqlite3_column_count(pSelect); + while( rc==SQLITE_ROW ){ + z = (const char*)sqlite3_column_text(pSelect, 0); + utf8_printf(p->out, "%s", z); + for(i=1; iout, ",%s", sqlite3_column_text(pSelect, i)); } - rc = sqlite3_step(pSelect); - nResult = sqlite3_column_count(pSelect); - while( rc==SQLITE_ROW ){ - z = (const char*)sqlite3_column_text(pSelect, 0); - utf8_printf(p->out, "%s", z); - for(i=1; iout, ",%s", sqlite3_column_text(pSelect, i)); - } - if( z==0 ) z = ""; - while( z[0] && (z[0]!='-' || z[1]!='-') ) z++; - if( z[0] ){ - raw_printf(p->out, "\n;\n"); - }else{ - raw_printf(p->out, ";\n"); - } - rc = sqlite3_step(pSelect); - } - rc = sqlite3_finalize(pSelect); - if( rc!=SQLITE_OK ){ - utf8_printf(p->out, "/**** ERROR: (%d) %s *****/\n", rc, - sqlite3_errmsg(p->db)); - if( (rc&0xff)!=SQLITE_CORRUPT ) p->nErr++; + if( z==0 ) z = ""; + while( z[0] && (z[0]!='-' || z[1]!='-') ) z++; + if( z[0] ){ + raw_printf(p->out, "\n;\n"); + }else{ + raw_printf(p->out, ";\n"); } - return rc; + rc = sqlite3_step(pSelect); + } + rc = sqlite3_finalize(pSelect); + if( rc!=SQLITE_OK ){ + utf8_printf(p->out, "/**** ERROR: (%d) %s *****/\n", rc, + sqlite3_errmsg(p->db)); + if( (rc&0xff)!=SQLITE_CORRUPT ) p->nErr++; + } + return rc; } /* ** Allocate space and save off string indicating current error. */ static char *save_err_msg( - sqlite3 *db, /* Database to query */ - const char *zWhen, /* Qualifier (format) wrapper */ - int rc /* Error code returned from API */ + sqlite3 *db, /* Database to query */ + const char *zWhen, /* Qualifier (format) wrapper */ + int rc /* Error code returned from API */ ){ - if( zWhen==0 ) - zWhen = "%s (%d)"; - return sqlite3_mprintf(zWhen, sqlite3_errmsg(db), rc); + if( zWhen==0 ) + zWhen = "%s (%d)"; + return sqlite3_mprintf(zWhen, sqlite3_errmsg(db), rc); } #ifdef __linux__ @@ -13678,34 +13678,34 @@ static char *save_err_msg( ** Attempt to display I/O stats on Linux using /proc/PID/io */ static void displayLinuxIoStats(FILE *out){ - FILE *in; - char z[200]; - sqlite3_snprintf(sizeof(z), z, "/proc/%d/io", getpid()); - in = fopen(z, "rb"); - if( in==0 ) return; - while( fgets(z, sizeof(z), in)!=0 ){ - static const struct { - const char *zPattern; - const char *zDesc; - } aTrans[] = { - { "rchar: ", "Bytes received by read():" }, - { "wchar: ", "Bytes sent to write():" }, - { "syscr: ", "Read() system calls:" }, - { "syscw: ", "Write() system calls:" }, - { "read_bytes: ", "Bytes read from storage:" }, - { "write_bytes: ", "Bytes written to storage:" }, - { "cancelled_write_bytes: ", "Cancelled write bytes:" }, - }; - int i; - for(i=0; i1 ){ - sqlite3_snprintf(sizeof(zLine), zLine, zFormat, iCur, iHiwtr); - }else{ - sqlite3_snprintf(sizeof(zLine), zLine, zFormat, iHiwtr); - } - raw_printf(p->out, "%-36s %s\n", zLabel, zLine); + sqlite3_int64 iCur = -1; + sqlite3_int64 iHiwtr = -1; + int i, nPercent; + char zLine[200]; + sqlite3_status64(iStatusCtrl, &iCur, &iHiwtr, bReset); + for(i=0, nPercent=0; zFormat[i]; i++){ + if( zFormat[i]=='%' ) nPercent++; + } + if( nPercent>1 ){ + sqlite3_snprintf(sizeof(zLine), zLine, zFormat, iCur, iHiwtr); + }else{ + sqlite3_snprintf(sizeof(zLine), zLine, zFormat, iHiwtr); + } + raw_printf(p->out, "%-36s %s\n", zLabel, zLine); } /* ** Display memory stats. */ static int display_stats( - sqlite3 *db, /* Database to query */ - ShellState *pArg, /* Pointer to ShellState */ - int bReset /* True to reset the stats */ + sqlite3 *db, /* Database to query */ + ShellState *pArg, /* Pointer to ShellState */ + int bReset /* True to reset the stats */ ){ - int iCur; - int iHiwtr; - FILE *out; - if( pArg==0 || pArg->out==0 ) return 0; - out = pArg->out; - - if( pArg->pStmt && pArg->statsOn==2 ){ - int nCol, i, x; - sqlite3_stmt *pStmt = pArg->pStmt; - char z[100]; - nCol = sqlite3_column_count(pStmt); - raw_printf(out, "%-36s %d\n", "Number of output columns:", nCol); - for(i=0; iout==0 ) return 0; + out = pArg->out; + + if( pArg->pStmt && pArg->statsOn==2 ){ + int nCol, i, x; + sqlite3_stmt *pStmt = pArg->pStmt; + char z[100]; + nCol = sqlite3_column_count(pStmt); + raw_printf(out, "%-36s %d\n", "Number of output columns:", nCol); + for(i=0; istatsOn==3 ){ - if( pArg->pStmt ){ - iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_VM_STEP, bReset); - raw_printf(pArg->out, "VM-steps: %d\n", iCur); - } - return 0; + if( pArg->statsOn==3 ){ + if( pArg->pStmt ){ + iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_VM_STEP, bReset); + raw_printf(pArg->out, "VM-steps: %d\n", iCur); } - - displayStatLine(pArg, "Memory Used:", - "%lld (max %lld) bytes", SQLITE_STATUS_MEMORY_USED, bReset); - displayStatLine(pArg, "Number of Outstanding Allocations:", - "%lld (max %lld)", SQLITE_STATUS_MALLOC_COUNT, bReset); - if( pArg->shellFlgs & SHFLG_Pagecache ){ - displayStatLine(pArg, "Number of Pcache Pages Used:", - "%lld (max %lld) pages", SQLITE_STATUS_PAGECACHE_USED, bReset); - } - displayStatLine(pArg, "Number of Pcache Overflow Bytes:", - "%lld (max %lld) bytes", SQLITE_STATUS_PAGECACHE_OVERFLOW, bReset); - displayStatLine(pArg, "Largest Allocation:", - "%lld bytes", SQLITE_STATUS_MALLOC_SIZE, bReset); - displayStatLine(pArg, "Largest Pcache Allocation:", - "%lld bytes", SQLITE_STATUS_PAGECACHE_SIZE, bReset); + return 0; + } + + displayStatLine(pArg, "Memory Used:", + "%lld (max %lld) bytes", SQLITE_STATUS_MEMORY_USED, bReset); + displayStatLine(pArg, "Number of Outstanding Allocations:", + "%lld (max %lld)", SQLITE_STATUS_MALLOC_COUNT, bReset); + if( pArg->shellFlgs & SHFLG_Pagecache ){ + displayStatLine(pArg, "Number of Pcache Pages Used:", + "%lld (max %lld) pages", SQLITE_STATUS_PAGECACHE_USED, bReset); + } + displayStatLine(pArg, "Number of Pcache Overflow Bytes:", + "%lld (max %lld) bytes", SQLITE_STATUS_PAGECACHE_OVERFLOW, bReset); + displayStatLine(pArg, "Largest Allocation:", + "%lld bytes", SQLITE_STATUS_MALLOC_SIZE, bReset); + displayStatLine(pArg, "Largest Pcache Allocation:", + "%lld bytes", SQLITE_STATUS_PAGECACHE_SIZE, bReset); #ifdef YYTRACKMAXSTACKDEPTH - displayStatLine(pArg, "Deepest Parser Stack:", - "%lld (max %lld)", SQLITE_STATUS_PARSER_STACK, bReset); + displayStatLine(pArg, "Deepest Parser Stack:", + "%lld (max %lld)", SQLITE_STATUS_PARSER_STACK, bReset); #endif - if( db ){ - if( pArg->shellFlgs & SHFLG_Lookaside ){ - iHiwtr = iCur = -1; - sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_USED, - &iCur, &iHiwtr, bReset); - raw_printf(pArg->out, - "Lookaside Slots Used: %d (max %d)\n", - iCur, iHiwtr); - sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_HIT, - &iCur, &iHiwtr, bReset); - raw_printf(pArg->out, "Successful lookaside attempts: %d\n", - iHiwtr); - sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE, - &iCur, &iHiwtr, bReset); - raw_printf(pArg->out, "Lookaside failures due to size: %d\n", - iHiwtr); - sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL, - &iCur, &iHiwtr, bReset); - raw_printf(pArg->out, "Lookaside failures due to OOM: %d\n", - iHiwtr); - } - iHiwtr = iCur = -1; - sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_USED, &iCur, &iHiwtr, bReset); - raw_printf(pArg->out, "Pager Heap Usage: %d bytes\n", + if( db ){ + if( pArg->shellFlgs & SHFLG_Lookaside ){ + iHiwtr = iCur = -1; + sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_USED, + &iCur, &iHiwtr, bReset); + raw_printf(pArg->out, + "Lookaside Slots Used: %d (max %d)\n", + iCur, iHiwtr); + sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_HIT, + &iCur, &iHiwtr, bReset); + raw_printf(pArg->out, "Successful lookaside attempts: %d\n", + iHiwtr); + sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE, + &iCur, &iHiwtr, bReset); + raw_printf(pArg->out, "Lookaside failures due to size: %d\n", + iHiwtr); + sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL, + &iCur, &iHiwtr, bReset); + raw_printf(pArg->out, "Lookaside failures due to OOM: %d\n", + iHiwtr); + } + iHiwtr = iCur = -1; + sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_USED, &iCur, &iHiwtr, bReset); + raw_printf(pArg->out, "Pager Heap Usage: %d bytes\n", iCur); - iHiwtr = iCur = -1; - sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_HIT, &iCur, &iHiwtr, 1); - raw_printf(pArg->out, "Page cache hits: %d\n", iCur); - iHiwtr = iCur = -1; - sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_MISS, &iCur, &iHiwtr, 1); - raw_printf(pArg->out, "Page cache misses: %d\n", iCur); - iHiwtr = iCur = -1; - sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_WRITE, &iCur, &iHiwtr, 1); - raw_printf(pArg->out, "Page cache writes: %d\n", iCur); - iHiwtr = iCur = -1; - sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_SPILL, &iCur, &iHiwtr, 1); - raw_printf(pArg->out, "Page cache spills: %d\n", iCur); - iHiwtr = iCur = -1; - sqlite3_db_status(db, SQLITE_DBSTATUS_SCHEMA_USED, &iCur, &iHiwtr, bReset); - raw_printf(pArg->out, "Schema Heap Usage: %d bytes\n", + iHiwtr = iCur = -1; + sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_HIT, &iCur, &iHiwtr, 1); + raw_printf(pArg->out, "Page cache hits: %d\n", iCur); + iHiwtr = iCur = -1; + sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_MISS, &iCur, &iHiwtr, 1); + raw_printf(pArg->out, "Page cache misses: %d\n", iCur); + iHiwtr = iCur = -1; + sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_WRITE, &iCur, &iHiwtr, 1); + raw_printf(pArg->out, "Page cache writes: %d\n", iCur); + iHiwtr = iCur = -1; + sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_SPILL, &iCur, &iHiwtr, 1); + raw_printf(pArg->out, "Page cache spills: %d\n", iCur); + iHiwtr = iCur = -1; + sqlite3_db_status(db, SQLITE_DBSTATUS_SCHEMA_USED, &iCur, &iHiwtr, bReset); + raw_printf(pArg->out, "Schema Heap Usage: %d bytes\n", iCur); - iHiwtr = iCur = -1; - sqlite3_db_status(db, SQLITE_DBSTATUS_STMT_USED, &iCur, &iHiwtr, bReset); - raw_printf(pArg->out, "Statement Heap/Lookaside Usage: %d bytes\n", + iHiwtr = iCur = -1; + sqlite3_db_status(db, SQLITE_DBSTATUS_STMT_USED, &iCur, &iHiwtr, bReset); + raw_printf(pArg->out, "Statement Heap/Lookaside Usage: %d bytes\n", iCur); - } - - if( pArg->pStmt ){ - iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_FULLSCAN_STEP, - bReset); - raw_printf(pArg->out, "Fullscan Steps: %d\n", iCur); - iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_SORT, bReset); - raw_printf(pArg->out, "Sort Operations: %d\n", iCur); - iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_AUTOINDEX,bReset); - raw_printf(pArg->out, "Autoindex Inserts: %d\n", iCur); - iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_VM_STEP, bReset); - raw_printf(pArg->out, "Virtual Machine Steps: %d\n", iCur); - iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_REPREPARE,bReset); - raw_printf(pArg->out, "Reprepare operations: %d\n", iCur); - iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_RUN, bReset); - raw_printf(pArg->out, "Number of times run: %d\n", iCur); - iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_MEMUSED, bReset); - raw_printf(pArg->out, "Memory used by prepared stmt: %d\n", iCur); - } + } + + if( pArg->pStmt ){ + iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_FULLSCAN_STEP, + bReset); + raw_printf(pArg->out, "Fullscan Steps: %d\n", iCur); + iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_SORT, bReset); + raw_printf(pArg->out, "Sort Operations: %d\n", iCur); + iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_AUTOINDEX,bReset); + raw_printf(pArg->out, "Autoindex Inserts: %d\n", iCur); + iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_VM_STEP, bReset); + raw_printf(pArg->out, "Virtual Machine Steps: %d\n", iCur); + iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_REPREPARE,bReset); + raw_printf(pArg->out, "Reprepare operations: %d\n", iCur); + iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_RUN, bReset); + raw_printf(pArg->out, "Number of times run: %d\n", iCur); + iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_MEMUSED, bReset); + raw_printf(pArg->out, "Memory used by prepared stmt: %d\n", iCur); + } #ifdef __linux__ - displayLinuxIoStats(pArg->out); + displayLinuxIoStats(pArg->out); #endif - /* Do not remove this machine readable comment: extra-stats-output-here */ + /* Do not remove this machine readable comment: extra-stats-output-here */ - return 0; + return 0; } /* ** Display scan stats. */ static void display_scanstats( - sqlite3 *db, /* Database to query */ - ShellState *pArg /* Pointer to ShellState */ + sqlite3 *db, /* Database to query */ + ShellState *pArg /* Pointer to ShellState */ ){ #ifndef SQLITE_ENABLE_STMT_SCANSTATUS - UNUSED_PARAMETER(db); - UNUSED_PARAMETER(pArg); + UNUSED_PARAMETER(db); + UNUSED_PARAMETER(pArg); #else - int i, k, n, mx; - raw_printf(pArg->out, "-------- scanstats --------\n"); - mx = 0; - for(k=0; k<=mx; k++){ - double rEstLoop = 1.0; - for(i=n=0; 1; i++){ - sqlite3_stmt *p = pArg->pStmt; - sqlite3_int64 nLoop, nVisit; - double rEst; - int iSid; - const char *zExplain; - if( sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_NLOOP, (void*)&nLoop) ){ - break; - } - sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_SELECTID, (void*)&iSid); - if( iSid>mx ) mx = iSid; - if( iSid!=k ) continue; - if( n==0 ){ - rEstLoop = (double)nLoop; - if( k>0 ) raw_printf(pArg->out, "-------- subquery %d -------\n", k); - } - n++; - sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_NVISIT, (void*)&nVisit); - sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_EST, (void*)&rEst); - sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_EXPLAIN, (void*)&zExplain); - utf8_printf(pArg->out, "Loop %2d: %s\n", n, zExplain); - rEstLoop *= rEst; - raw_printf(pArg->out, - " nLoop=%-8lld nRow=%-8lld estRow=%-8lld estRow/Loop=%-8g\n", - nLoop, nVisit, (sqlite3_int64)(rEstLoop+0.5), rEst - ); - } - } - raw_printf(pArg->out, "---------------------------\n"); + int i, k, n, mx; + raw_printf(pArg->out, "-------- scanstats --------\n"); + mx = 0; + for(k=0; k<=mx; k++){ + double rEstLoop = 1.0; + for(i=n=0; 1; i++){ + sqlite3_stmt *p = pArg->pStmt; + sqlite3_int64 nLoop, nVisit; + double rEst; + int iSid; + const char *zExplain; + if( sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_NLOOP, (void*)&nLoop) ){ + break; + } + sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_SELECTID, (void*)&iSid); + if( iSid>mx ) mx = iSid; + if( iSid!=k ) continue; + if( n==0 ){ + rEstLoop = (double)nLoop; + if( k>0 ) raw_printf(pArg->out, "-------- subquery %d -------\n", k); + } + n++; + sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_NVISIT, (void*)&nVisit); + sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_EST, (void*)&rEst); + sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_EXPLAIN, (void*)&zExplain); + utf8_printf(pArg->out, "Loop %2d: %s\n", n, zExplain); + rEstLoop *= rEst; + raw_printf(pArg->out, + " nLoop=%-8lld nRow=%-8lld estRow=%-8lld estRow/Loop=%-8g\n", + nLoop, nVisit, (sqlite3_int64)(rEstLoop+0.5), rEst + ); + } + } + raw_printf(pArg->out, "---------------------------\n"); #endif } @@ -13929,11 +13929,11 @@ static void display_scanstats( ** Otherwise, return zero. */ static int str_in_array(const char *zStr, const char **azArray){ - int i; - for(i=0; azArray[i]; i++){ - if( 0==strcmp(zStr, azArray[i]) ) return 1; - } - return 0; + int i; + for(i=0; azArray[i]; i++){ + if( 0==strcmp(zStr, azArray[i]) ) return 1; + } + return 0; } /* @@ -13955,93 +13955,93 @@ static int str_in_array(const char *zStr, const char **azArray){ ** and "Goto" by 2 spaces. */ static void explain_data_prepare(ShellState *p, sqlite3_stmt *pSql){ - const char *zSql; /* The text of the SQL statement */ - const char *z; /* Used to check if this is an EXPLAIN */ - int *abYield = 0; /* True if op is an OP_Yield */ - int nAlloc = 0; /* Allocated size of p->aiIndent[], abYield */ - int iOp; /* Index of operation in p->aiIndent[] */ - - const char *azNext[] = { "Next", "Prev", "VPrev", "VNext", "SorterNext", 0 }; - const char *azYield[] = { "Yield", "SeekLT", "SeekGT", "RowSetRead", - "Rewind", 0 }; - const char *azGoto[] = { "Goto", 0 }; - - /* Try to figure out if this is really an EXPLAIN statement. If this + const char *zSql; /* The text of the SQL statement */ + const char *z; /* Used to check if this is an EXPLAIN */ + int *abYield = 0; /* True if op is an OP_Yield */ + int nAlloc = 0; /* Allocated size of p->aiIndent[], abYield */ + int iOp; /* Index of operation in p->aiIndent[] */ + + const char *azNext[] = { "Next", "Prev", "VPrev", "VNext", "SorterNext", 0 }; + const char *azYield[] = { "Yield", "SeekLT", "SeekGT", "RowSetRead", + "Rewind", 0 }; + const char *azGoto[] = { "Goto", 0 }; + + /* Try to figure out if this is really an EXPLAIN statement. If this ** cannot be verified, return early. */ - if( sqlite3_column_count(pSql)!=8 ){ - p->cMode = p->mode; - return; - } - zSql = sqlite3_sql(pSql); - if( zSql==0 ) return; - for(z=zSql; *z==' ' || *z=='\t' || *z=='\n' || *z=='\f' || *z=='\r'; z++); - if( sqlite3_strnicmp(z, "explain", 7) ){ - p->cMode = p->mode; - return; - } - - for(iOp=0; SQLITE_ROW==sqlite3_step(pSql); iOp++){ - int i; - int iAddr = sqlite3_column_int(pSql, 0); - const char *zOp = (const char*)sqlite3_column_text(pSql, 1); + if( sqlite3_column_count(pSql)!=8 ){ + p->cMode = p->mode; + return; + } + zSql = sqlite3_sql(pSql); + if( zSql==0 ) return; + for(z=zSql; *z==' ' || *z=='\t' || *z=='\n' || *z=='\f' || *z=='\r'; z++); + if( sqlite3_strnicmp(z, "explain", 7) ){ + p->cMode = p->mode; + return; + } + + for(iOp=0; SQLITE_ROW==sqlite3_step(pSql); iOp++){ + int i; + int iAddr = sqlite3_column_int(pSql, 0); + const char *zOp = (const char*)sqlite3_column_text(pSql, 1); - /* Set p2 to the P2 field of the current opcode. Then, assuming that + /* Set p2 to the P2 field of the current opcode. Then, assuming that ** p2 is an instruction address, set variable p2op to the index of that ** instruction in the aiIndent[] array. p2 and p2op may be different if ** the current instruction is part of a sub-program generated by an ** SQL trigger or foreign key. */ - int p2 = sqlite3_column_int(pSql, 3); - int p2op = (p2 + (iOp-iAddr)); + int p2 = sqlite3_column_int(pSql, 3); + int p2op = (p2 + (iOp-iAddr)); - /* Grow the p->aiIndent array as required */ - if( iOp>=nAlloc ){ - if( iOp==0 ){ - /* Do further verfication that this is explain output. Abort if + /* Grow the p->aiIndent array as required */ + if( iOp>=nAlloc ){ + if( iOp==0 ){ + /* Do further verfication that this is explain output. Abort if ** it is not */ - static const char *explainCols[] = { - "addr", "opcode", "p1", "p2", "p3", "p4", "p5", "comment" }; - int jj; - for(jj=0; jjcMode = p->mode; - sqlite3_reset(pSql); - return; - } - } - } - nAlloc += 100; - p->aiIndent = (int*)sqlite3_realloc64(p->aiIndent, nAlloc*sizeof(int)); - if( p->aiIndent==0 ) shell_out_of_memory(); - abYield = (int*)sqlite3_realloc64(abYield, nAlloc*sizeof(int)); - if( abYield==0 ) shell_out_of_memory(); + static const char *explainCols[] = { + "addr", "opcode", "p1", "p2", "p3", "p4", "p5", "comment" }; + int jj; + for(jj=0; jjcMode = p->mode; + sqlite3_reset(pSql); + return; + } } - abYield[iOp] = str_in_array(zOp, azYield); - p->aiIndent[iOp] = 0; - p->nIndent = iOp+1; + } + nAlloc += 100; + p->aiIndent = (int*)sqlite3_realloc64(p->aiIndent, nAlloc*sizeof(int)); + if( p->aiIndent==0 ) shell_out_of_memory(); + abYield = (int*)sqlite3_realloc64(abYield, nAlloc*sizeof(int)); + if( abYield==0 ) shell_out_of_memory(); + } + abYield[iOp] = str_in_array(zOp, azYield); + p->aiIndent[iOp] = 0; + p->nIndent = iOp+1; - if( str_in_array(zOp, azNext) ){ - for(i=p2op; iaiIndent[i] += 2; - } - if( str_in_array(zOp, azGoto) && p2opnIndent - && (abYield[p2op] || sqlite3_column_int(pSql, 2)) - ){ - for(i=p2op; iaiIndent[i] += 2; - } + if( str_in_array(zOp, azNext) ){ + for(i=p2op; iaiIndent[i] += 2; + } + if( str_in_array(zOp, azGoto) && p2opnIndent + && (abYield[p2op] || sqlite3_column_int(pSql, 2)) + ){ + for(i=p2op; iaiIndent[i] += 2; } + } - p->iIndent = 0; - sqlite3_free(abYield); - sqlite3_reset(pSql); + p->iIndent = 0; + sqlite3_free(abYield); + sqlite3_reset(pSql); } /* ** Free the array allocated by explain_data_prepare(). */ static void explain_data_delete(ShellState *p){ - sqlite3_free(p->aiIndent); - p->aiIndent = 0; - p->nIndent = 0; - p->iIndent = 0; + sqlite3_free(p->aiIndent); + p->aiIndent = 0; + p->nIndent = 0; + p->iIndent = 0; } /* @@ -14050,33 +14050,33 @@ static void explain_data_delete(ShellState *p){ static unsigned int savedSelectTrace; static unsigned int savedWhereTrace; static void disable_debug_trace_modes(void){ - unsigned int zero = 0; - sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 0, &savedSelectTrace); - sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 1, &zero); - sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 2, &savedWhereTrace); - sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 3, &zero); + unsigned int zero = 0; + sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 0, &savedSelectTrace); + sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 1, &zero); + sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 2, &savedWhereTrace); + sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 3, &zero); } static void restore_debug_trace_modes(void){ - sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 1, &savedSelectTrace); - sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 3, &savedWhereTrace); + sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 1, &savedSelectTrace); + sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 3, &savedWhereTrace); } /* Create the TEMP table used to store parameter bindings */ static void bind_table_init(ShellState *p){ - int wrSchema = 0; - int defensiveMode = 0; - sqlite3_db_config(p->db, SQLITE_DBCONFIG_DEFENSIVE, -1, &defensiveMode); - sqlite3_db_config(p->db, SQLITE_DBCONFIG_DEFENSIVE, 0, 0); - sqlite3_db_config(p->db, SQLITE_DBCONFIG_WRITABLE_SCHEMA, -1, &wrSchema); - sqlite3_db_config(p->db, SQLITE_DBCONFIG_WRITABLE_SCHEMA, 1, 0); - sqlite3_exec(p->db, - "CREATE TABLE IF NOT EXISTS temp.sqlite_parameters(\n" - " key TEXT PRIMARY KEY,\n" - " value\n" - ") WITHOUT ROWID;", - 0, 0, 0); - sqlite3_db_config(p->db, SQLITE_DBCONFIG_WRITABLE_SCHEMA, wrSchema, 0); - sqlite3_db_config(p->db, SQLITE_DBCONFIG_DEFENSIVE, defensiveMode, 0); + int wrSchema = 0; + int defensiveMode = 0; + sqlite3_db_config(p->db, SQLITE_DBCONFIG_DEFENSIVE, -1, &defensiveMode); + sqlite3_db_config(p->db, SQLITE_DBCONFIG_DEFENSIVE, 0, 0); + sqlite3_db_config(p->db, SQLITE_DBCONFIG_WRITABLE_SCHEMA, -1, &wrSchema); + sqlite3_db_config(p->db, SQLITE_DBCONFIG_WRITABLE_SCHEMA, 1, 0); + sqlite3_exec(p->db, + "CREATE TABLE IF NOT EXISTS temp.sqlite_parameters(\n" + " key TEXT PRIMARY KEY,\n" + " value\n" + ") WITHOUT ROWID;", + 0, 0, 0); + sqlite3_db_config(p->db, SQLITE_DBCONFIG_WRITABLE_SCHEMA, wrSchema, 0); + sqlite3_db_config(p->db, SQLITE_DBCONFIG_DEFENSIVE, defensiveMode, 0); } /* @@ -14092,37 +14092,37 @@ static void bind_table_init(ShellState *p){ ** tables. The table must be in the TEMP schema. */ static void bind_prepared_stmt(ShellState *pArg, sqlite3_stmt *pStmt){ - int nVar; - int i; - int rc; - sqlite3_stmt *pQ = 0; - - nVar = sqlite3_bind_parameter_count(pStmt); - if( nVar==0 ) return; /* Nothing to do */ - if( sqlite3_table_column_metadata(pArg->db, "TEMP", "sqlite_parameters", - "key", 0, 0, 0, 0, 0)!=SQLITE_OK ){ - return; /* Parameter table does not exist */ - } - rc = sqlite3_prepare_v2(pArg->db, - "SELECT value FROM temp.sqlite_parameters" - " WHERE key=?1", -1, &pQ, 0); - if( rc || pQ==0 ) return; - for(i=1; i<=nVar; i++){ - char zNum[30]; - const char *zVar = sqlite3_bind_parameter_name(pStmt, i); - if( zVar==0 ){ - sqlite3_snprintf(sizeof(zNum),zNum,"?%d",i); - zVar = zNum; - } - sqlite3_bind_text(pQ, 1, zVar, -1, SQLITE_STATIC); - if( sqlite3_step(pQ)==SQLITE_ROW ){ - sqlite3_bind_value(pStmt, i, sqlite3_column_value(pQ, 0)); - }else{ - sqlite3_bind_null(pStmt, i); - } - sqlite3_reset(pQ); + int nVar; + int i; + int rc; + sqlite3_stmt *pQ = 0; + + nVar = sqlite3_bind_parameter_count(pStmt); + if( nVar==0 ) return; /* Nothing to do */ + if( sqlite3_table_column_metadata(pArg->db, "TEMP", "sqlite_parameters", + "key", 0, 0, 0, 0, 0)!=SQLITE_OK ){ + return; /* Parameter table does not exist */ + } + rc = sqlite3_prepare_v2(pArg->db, + "SELECT value FROM temp.sqlite_parameters" + " WHERE key=?1", -1, &pQ, 0); + if( rc || pQ==0 ) return; + for(i=1; i<=nVar; i++){ + char zNum[30]; + const char *zVar = sqlite3_bind_parameter_name(pStmt, i); + if( zVar==0 ){ + sqlite3_snprintf(sizeof(zNum),zNum,"?%d",i); + zVar = zNum; + } + sqlite3_bind_text(pQ, 1, zVar, -1, SQLITE_STATIC); + if( sqlite3_step(pQ)==SQLITE_ROW ){ + sqlite3_bind_value(pStmt, i, sqlite3_column_value(pQ, 0)); + }else{ + sqlite3_bind_null(pStmt, i); } - sqlite3_finalize(pQ); + sqlite3_reset(pQ); + } + sqlite3_finalize(pQ); } /* @@ -14154,39 +14154,39 @@ static void bind_prepared_stmt(ShellState *pArg, sqlite3_stmt *pStmt){ ** characters */ static void print_box_line(FILE *out, int N){ - const char zDash[] = - BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 - BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24; - const int nDash = sizeof(zDash) - 1; - N *= 3; - while( N>nDash ){ - utf8_printf(out, zDash); - N -= nDash; - } - utf8_printf(out, "%.*s", N, zDash); + const char zDash[] = + BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 + BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24; + const int nDash = sizeof(zDash) - 1; + N *= 3; + while( N>nDash ){ + utf8_printf(out, zDash); + N -= nDash; + } + utf8_printf(out, "%.*s", N, zDash); } /* ** Draw a horizontal separator for a MODE_Box table. */ static void print_box_row_separator( - ShellState *p, - int nArg, - const char *zSep1, - const char *zSep2, - const char *zSep3 + ShellState *p, + int nArg, + const char *zSep1, + const char *zSep2, + const char *zSep3 ){ - int i; - if( nArg>0 ){ - utf8_printf(p->out, "%s", zSep1); - print_box_line(p->out, p->actualWidth[0]+2); - for(i=1; iout, "%s", zSep2); - print_box_line(p->out, p->actualWidth[i]+2); - } - utf8_printf(p->out, "%s", zSep3); + int i; + if( nArg>0 ){ + utf8_printf(p->out, "%s", zSep1); + print_box_line(p->out, p->actualWidth[0]+2); + for(i=1; iout, "%s", zSep2); + print_box_line(p->out, p->actualWidth[i]+2); } - fputs("\n", p->out); + utf8_printf(p->out, "%s", zSep3); + } + fputs("\n", p->out); } @@ -14202,227 +14202,227 @@ static void print_box_row_separator( ** any output. */ static void exec_prepared_stmt_columnar( - ShellState *p, /* Pointer to ShellState */ - sqlite3_stmt *pStmt /* Statment to run */ + ShellState *p, /* Pointer to ShellState */ + sqlite3_stmt *pStmt /* Statment to run */ ){ - sqlite3_int64 nRow = 0; - int nColumn = 0; - char **azData = 0; - sqlite3_int64 nAlloc = 0; - const char *z; - int rc; - sqlite3_int64 i, nData; - int j, nTotal, w, n; - const char *colSep = 0; - const char *rowSep = 0; - - rc = sqlite3_step(pStmt); - if( rc!=SQLITE_ROW ) return; - nColumn = sqlite3_column_count(pStmt); - nAlloc = nColumn*4; - if( nAlloc<=0 ) nAlloc = 1; - azData = sqlite3_malloc64( nAlloc*sizeof(char*) ); - if( azData==0 ) shell_out_of_memory(); + sqlite3_int64 nRow = 0; + int nColumn = 0; + char **azData = 0; + sqlite3_int64 nAlloc = 0; + const char *z; + int rc; + sqlite3_int64 i, nData; + int j, nTotal, w, n; + const char *colSep = 0; + const char *rowSep = 0; + + rc = sqlite3_step(pStmt); + if( rc!=SQLITE_ROW ) return; + nColumn = sqlite3_column_count(pStmt); + nAlloc = nColumn*4; + if( nAlloc<=0 ) nAlloc = 1; + azData = sqlite3_malloc64( nAlloc*sizeof(char*) ); + if( azData==0 ) shell_out_of_memory(); + for(i=0; i= nAlloc ){ + nAlloc *= 2; + azData = sqlite3_realloc64(azData, nAlloc*sizeof(char*)); + if( azData==0 ) shell_out_of_memory(); + } + nRow++; for(i=0; i= nAlloc ){ - nAlloc *= 2; - azData = sqlite3_realloc64(azData, nAlloc*sizeof(char*)); - if( azData==0 ) shell_out_of_memory(); - } - nRow++; + z = (const char*)sqlite3_column_text(pStmt,i); + azData[nRow*nColumn + i] = z ? strdup(z) : 0; + } + }while( sqlite3_step(pStmt)==SQLITE_ROW ); + if( nColumn>p->nWidth ){ + p->colWidth = realloc(p->colWidth, (nColumn+1)*2*sizeof(int)); + if( p->colWidth==0 ) shell_out_of_memory(); + for(i=p->nWidth; icolWidth[i] = 0; + p->nWidth = nColumn; + p->actualWidth = &p->colWidth[nColumn]; + } + memset(p->actualWidth, 0, nColumn*sizeof(int)); + for(i=0; icolWidth[i]; + if( w<0 ) w = -w; + p->actualWidth[i] = w; + } + nTotal = nColumn*(nRow+1); + for(i=0; inullValue; + n = strlenChar(z); + j = i%nColumn; + if( n>p->actualWidth[j] ) p->actualWidth[j] = n; + } + if( seenInterrupt ) goto columnar_end; + if( nColumn==0 ) goto columnar_end; + switch( p->cMode ){ + case MODE_Column: { + colSep = " "; + rowSep = "\n"; + if( p->showHeader ){ for(i=0; ip->nWidth ){ - p->colWidth = realloc(p->colWidth, (nColumn+1)*2*sizeof(int)); - if( p->colWidth==0 ) shell_out_of_memory(); - for(i=p->nWidth; icolWidth[i] = 0; - p->nWidth = nColumn; - p->actualWidth = &p->colWidth[nColumn]; - } - memset(p->actualWidth, 0, nColumn*sizeof(int)); - for(i=0; icolWidth[i]; - if( w<0 ) w = -w; - p->actualWidth[i] = w; - } - nTotal = nColumn*(nRow+1); - for(i=0; inullValue; - n = strlenChar(z); - j = i%nColumn; - if( n>p->actualWidth[j] ) p->actualWidth[j] = n; - } - if( seenInterrupt ) goto columnar_end; - if( nColumn==0 ) goto columnar_end; - switch( p->cMode ){ - case MODE_Column: { - colSep = " "; - rowSep = "\n"; - if( p->showHeader ){ - for(i=0; iactualWidth[i]; - if( p->colWidth[i]<0 ) w = -w; - utf8_width_print(p->out, w, azData[i]); - fputs(i==nColumn-1?"\n":" ", p->out); - } - for(i=0; iout, p->actualWidth[i]); - fputs(i==nColumn-1?"\n":" ", p->out); - } - } - break; - } - case MODE_Table: { - colSep = " | "; - rowSep = " |\n"; - print_row_separator(p, nColumn, "+"); - fputs("| ", p->out); - for(i=0; iactualWidth[i]; - n = strlenChar(azData[i]); - utf8_printf(p->out, "%*s%s%*s", (w-n)/2, "", azData[i], (w-n+1)/2, ""); - fputs(i==nColumn-1?" |\n":" | ", p->out); - } - print_row_separator(p, nColumn, "+"); - break; - } - case MODE_Markdown: { - colSep = " | "; - rowSep = " |\n"; - fputs("| ", p->out); - for(i=0; iactualWidth[i]; - n = strlenChar(azData[i]); - utf8_printf(p->out, "%*s%s%*s", (w-n)/2, "", azData[i], (w-n+1)/2, ""); - fputs(i==nColumn-1?" |\n":" | ", p->out); - } - print_row_separator(p, nColumn, "|"); - break; - } - case MODE_Box: { - colSep = " " BOX_13 " "; - rowSep = " " BOX_13 "\n"; - print_box_row_separator(p, nColumn, BOX_23, BOX_234, BOX_34); - utf8_printf(p->out, BOX_13 " "); - for(i=0; iactualWidth[i]; - n = strlenChar(azData[i]); - utf8_printf(p->out, "%*s%s%*s%s", - (w-n)/2, "", azData[i], (w-n+1)/2, "", - i==nColumn-1?" "BOX_13"\n":" "BOX_13" "); - } - print_box_row_separator(p, nColumn, BOX_123, BOX_1234, BOX_134); - break; + w = p->actualWidth[i]; + if( p->colWidth[i]<0 ) w = -w; + utf8_width_print(p->out, w, azData[i]); + fputs(i==nColumn-1?"\n":" ", p->out); } - } - for(i=nColumn, j=0; icMode!=MODE_Column ){ - utf8_printf(p->out, "%s", p->cMode==MODE_Box?BOX_13" ":"| "); - } - z = azData[i]; - if( z==0 ) z = p->nullValue; - w = p->actualWidth[j]; - if( p->colWidth[j]<0 ) w = -w; - utf8_width_print(p->out, w, z); - if( j==nColumn-1 ){ - utf8_printf(p->out, "%s", rowSep); - j = -1; - if( seenInterrupt ) goto columnar_end; - }else{ - utf8_printf(p->out, "%s", colSep); - } - } - if( p->cMode==MODE_Table ){ - print_row_separator(p, nColumn, "+"); - }else if( p->cMode==MODE_Box ){ - print_box_row_separator(p, nColumn, BOX_12, BOX_124, BOX_14); - } + for(i=0; iout, p->actualWidth[i]); + fputs(i==nColumn-1?"\n":" ", p->out); + } + } + break; + } + case MODE_Table: { + colSep = " | "; + rowSep = " |\n"; + print_row_separator(p, nColumn, "+"); + fputs("| ", p->out); + for(i=0; iactualWidth[i]; + n = strlenChar(azData[i]); + utf8_printf(p->out, "%*s%s%*s", (w-n)/2, "", azData[i], (w-n+1)/2, ""); + fputs(i==nColumn-1?" |\n":" | ", p->out); + } + print_row_separator(p, nColumn, "+"); + break; + } + case MODE_Markdown: { + colSep = " | "; + rowSep = " |\n"; + fputs("| ", p->out); + for(i=0; iactualWidth[i]; + n = strlenChar(azData[i]); + utf8_printf(p->out, "%*s%s%*s", (w-n)/2, "", azData[i], (w-n+1)/2, ""); + fputs(i==nColumn-1?" |\n":" | ", p->out); + } + print_row_separator(p, nColumn, "|"); + break; + } + case MODE_Box: { + colSep = " " BOX_13 " "; + rowSep = " " BOX_13 "\n"; + print_box_row_separator(p, nColumn, BOX_23, BOX_234, BOX_34); + utf8_printf(p->out, BOX_13 " "); + for(i=0; iactualWidth[i]; + n = strlenChar(azData[i]); + utf8_printf(p->out, "%*s%s%*s%s", + (w-n)/2, "", azData[i], (w-n+1)/2, "", + i==nColumn-1?" "BOX_13"\n":" "BOX_13" "); + } + print_box_row_separator(p, nColumn, BOX_123, BOX_1234, BOX_134); + break; + } + } + for(i=nColumn, j=0; icMode!=MODE_Column ){ + utf8_printf(p->out, "%s", p->cMode==MODE_Box?BOX_13" ":"| "); + } + z = azData[i]; + if( z==0 ) z = p->nullValue; + w = p->actualWidth[j]; + if( p->colWidth[j]<0 ) w = -w; + utf8_width_print(p->out, w, z); + if( j==nColumn-1 ){ + utf8_printf(p->out, "%s", rowSep); + j = -1; + if( seenInterrupt ) goto columnar_end; + }else{ + utf8_printf(p->out, "%s", colSep); + } + } + if( p->cMode==MODE_Table ){ + print_row_separator(p, nColumn, "+"); + }else if( p->cMode==MODE_Box ){ + print_box_row_separator(p, nColumn, BOX_12, BOX_124, BOX_14); + } columnar_end: - if( seenInterrupt ){ - utf8_printf(p->out, "Interrupt\n"); - } - nData = (nRow+1)*nColumn; - for(i=0; iout, "Interrupt\n"); + } + nData = (nRow+1)*nColumn; + for(i=0; icMode==MODE_Column - || pArg->cMode==MODE_Table - || pArg->cMode==MODE_Box - || pArg->cMode==MODE_Markdown - ){ - exec_prepared_stmt_columnar(pArg, pStmt); - return; - } - - /* perform the first step. this will tell us if we + int rc; + + if( pArg->cMode==MODE_Column + || pArg->cMode==MODE_Table + || pArg->cMode==MODE_Box + || pArg->cMode==MODE_Markdown + ){ + exec_prepared_stmt_columnar(pArg, pStmt); + return; + } + + /* perform the first step. this will tell us if we ** have a result set or not and how wide it is. */ - rc = sqlite3_step(pStmt); - /* if we have a result set... */ - if( SQLITE_ROW == rc ){ - /* allocate space for col name ptr, value ptr, and type */ - int nCol = sqlite3_column_count(pStmt); - void *pData = sqlite3_malloc64(3*nCol*sizeof(const char*) + 1); - if( !pData ){ - shell_out_of_memory(); - }else{ - char **azCols = (char **)pData; /* Names of result columns */ - char **azVals = &azCols[nCol]; /* Results */ - int *aiTypes = (int *)&azVals[nCol]; /* Result types */ - int i, x; - assert(sizeof(int) <= sizeof(char *)); - /* save off ptrs to column names */ - for(i=0; icMode==MODE_Insert ){ - azVals[i] = ""; - }else{ - azVals[i] = (char*)sqlite3_column_text(pStmt, i); - } - if( !azVals[i] && (aiTypes[i]!=SQLITE_NULL) ){ - rc = SQLITE_NOMEM; - break; /* from for */ - } - } /* end for */ - - /* if data and types extracted successfully... */ - if( SQLITE_ROW == rc ){ - /* call the supplied callback with the result row data */ - if( shell_callback(pArg, nCol, azVals, azCols, aiTypes) ){ - rc = SQLITE_ABORT; - }else{ - rc = sqlite3_step(pStmt); - } - } - } while( SQLITE_ROW == rc ); - sqlite3_free(pData); - if( pArg->cMode==MODE_Json ){ - fputs("]\n", pArg->out); - } + rc = sqlite3_step(pStmt); + /* if we have a result set... */ + if( SQLITE_ROW == rc ){ + /* allocate space for col name ptr, value ptr, and type */ + int nCol = sqlite3_column_count(pStmt); + void *pData = sqlite3_malloc64(3*nCol*sizeof(const char*) + 1); + if( !pData ){ + shell_out_of_memory(); + }else{ + char **azCols = (char **)pData; /* Names of result columns */ + char **azVals = &azCols[nCol]; /* Results */ + int *aiTypes = (int *)&azVals[nCol]; /* Result types */ + int i, x; + assert(sizeof(int) <= sizeof(char *)); + /* save off ptrs to column names */ + for(i=0; icMode==MODE_Insert ){ + azVals[i] = ""; + }else{ + azVals[i] = (char*)sqlite3_column_text(pStmt, i); + } + if( !azVals[i] && (aiTypes[i]!=SQLITE_NULL) ){ + rc = SQLITE_NOMEM; + break; /* from for */ + } + } /* end for */ + + /* if data and types extracted successfully... */ + if( SQLITE_ROW == rc ){ + /* call the supplied callback with the result row data */ + if( shell_callback(pArg, nCol, azVals, azCols, aiTypes) ){ + rc = SQLITE_ABORT; + }else{ + rc = sqlite3_step(pStmt); + } } + } while( SQLITE_ROW == rc ); + sqlite3_free(pData); + if( pArg->cMode==MODE_Json ){ + fputs("]\n", pArg->out); + } } + } } #ifndef SQLITE_OMIT_VIRTUALTABLE @@ -14437,18 +14437,18 @@ static void exec_prepared_stmt( ** caller to eventually free this buffer using sqlite3_free(). */ static int expertHandleSQL( - ShellState *pState, - const char *zSql, - char **pzErr + ShellState *pState, + const char *zSql, + char **pzErr ){ - assert( pState->expert.pExpert ); - assert( pzErr==0 || *pzErr==0 ); - return sqlite3_expert_sql(pState->expert.pExpert, zSql, pzErr); + assert( pState->expert.pExpert ); + assert( pzErr==0 || *pzErr==0 ); + return sqlite3_expert_sql(pState->expert.pExpert, zSql, pzErr); } /* ** This function is called either to silently clean up the object -** created by the ".expert" command (if bCancel==1), or to generate a +** created by the ".expert" command (if bCancel==1), or to generate a ** report from it and then clean it up (if bCancel==0). ** ** If successful, SQLITE_OK is returned. Otherwise, an SQLite error @@ -14457,102 +14457,102 @@ static int expertHandleSQL( ** caller to eventually free this buffer using sqlite3_free(). */ static int expertFinish( - ShellState *pState, - int bCancel, - char **pzErr + ShellState *pState, + int bCancel, + char **pzErr ){ - int rc = SQLITE_OK; - sqlite3expert *p = pState->expert.pExpert; - assert( p ); - assert( bCancel || pzErr==0 || *pzErr==0 ); - if( bCancel==0 ){ - FILE *out = pState->out; - int bVerbose = pState->expert.bVerbose; - - rc = sqlite3_expert_analyze(p, pzErr); - if( rc==SQLITE_OK ){ - int nQuery = sqlite3_expert_count(p); - int i; - - if( bVerbose ){ - const char *zCand = sqlite3_expert_report(p,0,EXPERT_REPORT_CANDIDATES); - raw_printf(out, "-- Candidates -----------------------------\n"); - raw_printf(out, "%s\n", zCand); - } - for(i=0; iexpert.pExpert = 0; - return rc; + int rc = SQLITE_OK; + sqlite3expert *p = pState->expert.pExpert; + assert( p ); + assert( bCancel || pzErr==0 || *pzErr==0 ); + if( bCancel==0 ){ + FILE *out = pState->out; + int bVerbose = pState->expert.bVerbose; + + rc = sqlite3_expert_analyze(p, pzErr); + if( rc==SQLITE_OK ){ + int nQuery = sqlite3_expert_count(p); + int i; + + if( bVerbose ){ + const char *zCand = sqlite3_expert_report(p,0,EXPERT_REPORT_CANDIDATES); + raw_printf(out, "-- Candidates -----------------------------\n"); + raw_printf(out, "%s\n", zCand); + } + for(i=0; iexpert.pExpert = 0; + return rc; } /* ** Implementation of ".expert" dot command. */ static int expertDotCommand( - ShellState *pState, /* Current shell tool state */ - char **azArg, /* Array of arguments passed to dot command */ - int nArg /* Number of entries in azArg[] */ + ShellState *pState, /* Current shell tool state */ + char **azArg, /* Array of arguments passed to dot command */ + int nArg /* Number of entries in azArg[] */ ){ - int rc = SQLITE_OK; - char *zErr = 0; - int i; - int iSample = 0; + int rc = SQLITE_OK; + char *zErr = 0; + int i; + int iSample = 0; - assert( pState->expert.pExpert==0 ); - memset(&pState->expert, 0, sizeof(ExpertInfo)); + assert( pState->expert.pExpert==0 ); + memset(&pState->expert, 0, sizeof(ExpertInfo)); - for(i=1; rc==SQLITE_OK && i=2 && 0==strncmp(z, "-verbose", n) ){ - pState->expert.bVerbose = 1; - } - else if( n>=2 && 0==strncmp(z, "-sample", n) ){ - if( i==(nArg-1) ){ - raw_printf(stderr, "option requires an argument: %s\n", z); - rc = SQLITE_ERROR; - }else{ - iSample = (int)integerValue(azArg[++i]); - if( iSample<0 || iSample>100 ){ - raw_printf(stderr, "value out of range: %s\n", azArg[i]); - rc = SQLITE_ERROR; - } - } - } - else{ - raw_printf(stderr, "unknown option: %s\n", z); - rc = SQLITE_ERROR; + for(i=1; rc==SQLITE_OK && i=2 && 0==strncmp(z, "-verbose", n) ){ + pState->expert.bVerbose = 1; + } + else if( n>=2 && 0==strncmp(z, "-sample", n) ){ + if( i==(nArg-1) ){ + raw_printf(stderr, "option requires an argument: %s\n", z); + rc = SQLITE_ERROR; + }else{ + iSample = (int)integerValue(azArg[++i]); + if( iSample<0 || iSample>100 ){ + raw_printf(stderr, "value out of range: %s\n", azArg[i]); + rc = SQLITE_ERROR; } + } + } + else{ + raw_printf(stderr, "unknown option: %s\n", z); + rc = SQLITE_ERROR; } + } - if( rc==SQLITE_OK ){ - pState->expert.pExpert = sqlite3_expert_new(pState->db, &zErr); - if( pState->expert.pExpert==0 ){ - raw_printf(stderr, "sqlite3_expert_new: %s\n", zErr); - rc = SQLITE_ERROR; - }else{ - sqlite3_expert_config( - pState->expert.pExpert, EXPERT_CONFIG_SAMPLE, iSample - ); - } + if( rc==SQLITE_OK ){ + pState->expert.pExpert = sqlite3_expert_new(pState->db, &zErr); + if( pState->expert.pExpert==0 ){ + raw_printf(stderr, "sqlite3_expert_new: %s\n", zErr); + rc = SQLITE_ERROR; + }else{ + sqlite3_expert_config( + pState->expert.pExpert, EXPERT_CONFIG_SAMPLE, iSample + ); } + } - return rc; + return rc; } #endif /* ifndef SQLITE_OMIT_VIRTUALTABLE */ @@ -14566,169 +14566,169 @@ static int expertDotCommand( ** and callback data argument. */ static int shell_exec( - ShellState *pArg, /* Pointer to ShellState */ - const char *zSql, /* SQL to be evaluated */ - char **pzErrMsg /* Error msg written here */ + ShellState *pArg, /* Pointer to ShellState */ + const char *zSql, /* SQL to be evaluated */ + char **pzErrMsg /* Error msg written here */ ){ - sqlite3_stmt *pStmt = NULL; /* Statement to execute. */ - int rc = SQLITE_OK; /* Return Code */ - int rc2; - const char *zLeftover; /* Tail of unprocessed SQL */ - sqlite3 *db = pArg->db; + sqlite3_stmt *pStmt = NULL; /* Statement to execute. */ + int rc = SQLITE_OK; /* Return Code */ + int rc2; + const char *zLeftover; /* Tail of unprocessed SQL */ + sqlite3 *db = pArg->db; - if( pzErrMsg ){ - *pzErrMsg = NULL; - } + if( pzErrMsg ){ + *pzErrMsg = NULL; + } #ifndef SQLITE_OMIT_VIRTUALTABLE - if( pArg->expert.pExpert ){ - rc = expertHandleSQL(pArg, zSql, pzErrMsg); - return expertFinish(pArg, (rc!=SQLITE_OK), pzErrMsg); - } + if( pArg->expert.pExpert ){ + rc = expertHandleSQL(pArg, zSql, pzErrMsg); + return expertFinish(pArg, (rc!=SQLITE_OK), pzErrMsg); + } #endif - while( zSql[0] && (SQLITE_OK == rc) ){ - static const char *zStmtSql; - rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, &zLeftover); - if( SQLITE_OK != rc ){ - if( pzErrMsg ){ - *pzErrMsg = save_err_msg(db, "in prepare, %s (%d)", rc); - } - }else{ - if( !pStmt ){ - /* this happens for a comment or white-space */ - zSql = zLeftover; - while( IsSpace(zSql[0]) ) zSql++; - continue; - } - zStmtSql = sqlite3_sql(pStmt); - if( zStmtSql==0 ) zStmtSql = ""; - while( IsSpace(zStmtSql[0]) ) zStmtSql++; - - /* save off the prepared statment handle and reset row count */ - if( pArg ){ - pArg->pStmt = pStmt; - pArg->cnt = 0; - } - - /* echo the sql statement if echo on */ - if( pArg && ShellHasFlag(pArg, SHFLG_Echo) ){ - utf8_printf(pArg->out, "%s\n", zStmtSql ? zStmtSql : zSql); - } - - /* Show the EXPLAIN QUERY PLAN if .eqp is on */ - if( pArg && pArg->autoEQP && sqlite3_stmt_isexplain(pStmt)==0 ){ - sqlite3_stmt *pExplain; - char *zEQP; - int triggerEQP = 0; - disable_debug_trace_modes(); - sqlite3_db_config(db, SQLITE_DBCONFIG_TRIGGER_EQP, -1, &triggerEQP); - if( pArg->autoEQP>=AUTOEQP_trigger ){ - sqlite3_db_config(db, SQLITE_DBCONFIG_TRIGGER_EQP, 1, 0); - } - zEQP = sqlite3_mprintf("EXPLAIN QUERY PLAN %s", zStmtSql); - rc = sqlite3_prepare_v2(db, zEQP, -1, &pExplain, 0); - if( rc==SQLITE_OK ){ - while( sqlite3_step(pExplain)==SQLITE_ROW ){ - const char *zEQPLine = (const char*)sqlite3_column_text(pExplain,3); - int iEqpId = sqlite3_column_int(pExplain, 0); - int iParentId = sqlite3_column_int(pExplain, 1); - if( zEQPLine==0 ) zEQPLine = ""; - if( zEQPLine[0]=='-' ) eqp_render(pArg); - eqp_append(pArg, iEqpId, iParentId, zEQPLine); - } - eqp_render(pArg); - } - sqlite3_finalize(pExplain); - sqlite3_free(zEQP); - if( pArg->autoEQP>=AUTOEQP_full ){ - /* Also do an EXPLAIN for ".eqp full" mode */ - zEQP = sqlite3_mprintf("EXPLAIN %s", zStmtSql); - rc = sqlite3_prepare_v2(db, zEQP, -1, &pExplain, 0); - if( rc==SQLITE_OK ){ - pArg->cMode = MODE_Explain; - explain_data_prepare(pArg, pExplain); - exec_prepared_stmt(pArg, pExplain); - explain_data_delete(pArg); - } - sqlite3_finalize(pExplain); - sqlite3_free(zEQP); - } - if( pArg->autoEQP>=AUTOEQP_trigger && triggerEQP==0 ){ - sqlite3_db_config(db, SQLITE_DBCONFIG_TRIGGER_EQP, 0, 0); - /* Reprepare pStmt before reactiving trace modes */ - sqlite3_finalize(pStmt); - sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0); - if( pArg ) pArg->pStmt = pStmt; - } - restore_debug_trace_modes(); - } - - if( pArg ){ - pArg->cMode = pArg->mode; - if( pArg->autoExplain ){ - if( sqlite3_stmt_isexplain(pStmt)==1 ){ - pArg->cMode = MODE_Explain; - } - if( sqlite3_stmt_isexplain(pStmt)==2 ){ - pArg->cMode = MODE_EQP; - } - } - - /* If the shell is currently in ".explain" mode, gather the extra + while( zSql[0] && (SQLITE_OK == rc) ){ + static const char *zStmtSql; + rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, &zLeftover); + if( SQLITE_OK != rc ){ + if( pzErrMsg ){ + *pzErrMsg = save_err_msg(db, "in prepare, %s (%d)", rc); + } + }else{ + if( !pStmt ){ + /* this happens for a comment or white-space */ + zSql = zLeftover; + while( IsSpace(zSql[0]) ) zSql++; + continue; + } + zStmtSql = sqlite3_sql(pStmt); + if( zStmtSql==0 ) zStmtSql = ""; + while( IsSpace(zStmtSql[0]) ) zStmtSql++; + + /* save off the prepared statment handle and reset row count */ + if( pArg ){ + pArg->pStmt = pStmt; + pArg->cnt = 0; + } + + /* echo the sql statement if echo on */ + if( pArg && ShellHasFlag(pArg, SHFLG_Echo) ){ + utf8_printf(pArg->out, "%s\n", zStmtSql ? zStmtSql : zSql); + } + + /* Show the EXPLAIN QUERY PLAN if .eqp is on */ + if( pArg && pArg->autoEQP && sqlite3_stmt_isexplain(pStmt)==0 ){ + sqlite3_stmt *pExplain; + char *zEQP; + int triggerEQP = 0; + disable_debug_trace_modes(); + sqlite3_db_config(db, SQLITE_DBCONFIG_TRIGGER_EQP, -1, &triggerEQP); + if( pArg->autoEQP>=AUTOEQP_trigger ){ + sqlite3_db_config(db, SQLITE_DBCONFIG_TRIGGER_EQP, 1, 0); + } + zEQP = sqlite3_mprintf("EXPLAIN QUERY PLAN %s", zStmtSql); + rc = sqlite3_prepare_v2(db, zEQP, -1, &pExplain, 0); + if( rc==SQLITE_OK ){ + while( sqlite3_step(pExplain)==SQLITE_ROW ){ + const char *zEQPLine = (const char*)sqlite3_column_text(pExplain,3); + int iEqpId = sqlite3_column_int(pExplain, 0); + int iParentId = sqlite3_column_int(pExplain, 1); + if( zEQPLine==0 ) zEQPLine = ""; + if( zEQPLine[0]=='-' ) eqp_render(pArg); + eqp_append(pArg, iEqpId, iParentId, zEQPLine); + } + eqp_render(pArg); + } + sqlite3_finalize(pExplain); + sqlite3_free(zEQP); + if( pArg->autoEQP>=AUTOEQP_full ){ + /* Also do an EXPLAIN for ".eqp full" mode */ + zEQP = sqlite3_mprintf("EXPLAIN %s", zStmtSql); + rc = sqlite3_prepare_v2(db, zEQP, -1, &pExplain, 0); + if( rc==SQLITE_OK ){ + pArg->cMode = MODE_Explain; + explain_data_prepare(pArg, pExplain); + exec_prepared_stmt(pArg, pExplain); + explain_data_delete(pArg); + } + sqlite3_finalize(pExplain); + sqlite3_free(zEQP); + } + if( pArg->autoEQP>=AUTOEQP_trigger && triggerEQP==0 ){ + sqlite3_db_config(db, SQLITE_DBCONFIG_TRIGGER_EQP, 0, 0); + /* Reprepare pStmt before reactiving trace modes */ + sqlite3_finalize(pStmt); + sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0); + if( pArg ) pArg->pStmt = pStmt; + } + restore_debug_trace_modes(); + } + + if( pArg ){ + pArg->cMode = pArg->mode; + if( pArg->autoExplain ){ + if( sqlite3_stmt_isexplain(pStmt)==1 ){ + pArg->cMode = MODE_Explain; + } + if( sqlite3_stmt_isexplain(pStmt)==2 ){ + pArg->cMode = MODE_EQP; + } + } + + /* If the shell is currently in ".explain" mode, gather the extra ** data required to add indents to the output.*/ - if( pArg->cMode==MODE_Explain ){ - explain_data_prepare(pArg, pStmt); - } - } + if( pArg->cMode==MODE_Explain ){ + explain_data_prepare(pArg, pStmt); + } + } - bind_prepared_stmt(pArg, pStmt); - exec_prepared_stmt(pArg, pStmt); - explain_data_delete(pArg); - eqp_render(pArg); + bind_prepared_stmt(pArg, pStmt); + exec_prepared_stmt(pArg, pStmt); + explain_data_delete(pArg); + eqp_render(pArg); - /* print usage stats if stats on */ - if( pArg && pArg->statsOn ){ - display_stats(db, pArg, 0); - } + /* print usage stats if stats on */ + if( pArg && pArg->statsOn ){ + display_stats(db, pArg, 0); + } - /* print loop-counters if required */ - if( pArg && pArg->scanstatsOn ){ - display_scanstats(db, pArg); - } + /* print loop-counters if required */ + if( pArg && pArg->scanstatsOn ){ + display_scanstats(db, pArg); + } - /* Finalize the statement just executed. If this fails, save a + /* Finalize the statement just executed. If this fails, save a ** copy of the error message. Otherwise, set zSql to point to the ** next statement to execute. */ - rc2 = sqlite3_finalize(pStmt); - if( rc!=SQLITE_NOMEM ) rc = rc2; - if( rc==SQLITE_OK ){ - zSql = zLeftover; - while( IsSpace(zSql[0]) ) zSql++; - }else if( pzErrMsg ){ - *pzErrMsg = save_err_msg(db, "stepping, %s (%d)", rc); - } + rc2 = sqlite3_finalize(pStmt); + if( rc!=SQLITE_NOMEM ) rc = rc2; + if( rc==SQLITE_OK ){ + zSql = zLeftover; + while( IsSpace(zSql[0]) ) zSql++; + }else if( pzErrMsg ){ + *pzErrMsg = save_err_msg(db, "stepping, %s (%d)", rc); + } - /* clear saved stmt handle */ - if( pArg ){ - pArg->pStmt = NULL; - } - } - } /* end while */ + /* clear saved stmt handle */ + if( pArg ){ + pArg->pStmt = NULL; + } + } + } /* end while */ - return rc; + return rc; } /* ** Release memory previously allocated by tableColumnList(). */ static void freeColumnList(char **azCol){ - int i; - for(i=1; azCol[i]; i++){ - sqlite3_free(azCol[i]); - } - /* azCol[0] is a static string */ - sqlite3_free(azCol); + int i; + for(i=1; azCol[i]; i++){ + sqlite3_free(azCol[i]); + } + /* azCol[0] is a static string */ + sqlite3_free(azCol); } /* @@ -14745,108 +14745,108 @@ static void freeColumnList(char **azCol){ ** by an entry with azCol[i]==0. */ static char **tableColumnList(ShellState *p, const char *zTab){ - char **azCol = 0; - sqlite3_stmt *pStmt; - char *zSql; - int nCol = 0; - int nAlloc = 0; - int nPK = 0; /* Number of PRIMARY KEY columns seen */ - int isIPK = 0; /* True if one PRIMARY KEY column of type INTEGER */ - int preserveRowid = ShellHasFlag(p, SHFLG_PreserveRowid); - int rc; - - zSql = sqlite3_mprintf("PRAGMA table_info=%Q", zTab); - rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); - sqlite3_free(zSql); - if( rc ) return 0; - while( sqlite3_step(pStmt)==SQLITE_ROW ){ - if( nCol>=nAlloc-2 ){ - nAlloc = nAlloc*2 + nCol + 10; - azCol = sqlite3_realloc(azCol, nAlloc*sizeof(azCol[0])); - if( azCol==0 ) shell_out_of_memory(); - } - azCol[++nCol] = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 1)); - if( sqlite3_column_int(pStmt, 5) ){ - nPK++; - if( nPK==1 - && sqlite3_stricmp((const char*)sqlite3_column_text(pStmt,2), - "INTEGER")==0 - ){ - isIPK = 1; - }else{ - isIPK = 0; - } - } - } - sqlite3_finalize(pStmt); - if( azCol==0 ) return 0; - azCol[0] = 0; - azCol[nCol+1] = 0; - - /* The decision of whether or not a rowid really needs to be preserved + char **azCol = 0; + sqlite3_stmt *pStmt; + char *zSql; + int nCol = 0; + int nAlloc = 0; + int nPK = 0; /* Number of PRIMARY KEY columns seen */ + int isIPK = 0; /* True if one PRIMARY KEY column of type INTEGER */ + int preserveRowid = ShellHasFlag(p, SHFLG_PreserveRowid); + int rc; + + zSql = sqlite3_mprintf("PRAGMA table_info=%Q", zTab); + rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); + sqlite3_free(zSql); + if( rc ) return 0; + while( sqlite3_step(pStmt)==SQLITE_ROW ){ + if( nCol>=nAlloc-2 ){ + nAlloc = nAlloc*2 + nCol + 10; + azCol = sqlite3_realloc(azCol, nAlloc*sizeof(azCol[0])); + if( azCol==0 ) shell_out_of_memory(); + } + azCol[++nCol] = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 1)); + if( sqlite3_column_int(pStmt, 5) ){ + nPK++; + if( nPK==1 + && sqlite3_stricmp((const char*)sqlite3_column_text(pStmt,2), + "INTEGER")==0 + ){ + isIPK = 1; + }else{ + isIPK = 0; + } + } + } + sqlite3_finalize(pStmt); + if( azCol==0 ) return 0; + azCol[0] = 0; + azCol[nCol+1] = 0; + + /* The decision of whether or not a rowid really needs to be preserved ** is tricky. We never need to preserve a rowid for a WITHOUT ROWID table ** or a table with an INTEGER PRIMARY KEY. We are unable to preserve ** rowids on tables where the rowid is inaccessible because there are other ** columns in the table named "rowid", "_rowid_", and "oid". */ - if( preserveRowid && isIPK ){ - /* If a single PRIMARY KEY column with type INTEGER was seen, then it + if( preserveRowid && isIPK ){ + /* If a single PRIMARY KEY column with type INTEGER was seen, then it ** might be an alise for the ROWID. But it might also be a WITHOUT ROWID ** table or a INTEGER PRIMARY KEY DESC column, neither of which are ** ROWID aliases. To distinguish these cases, check to see if ** there is a "pk" entry in "PRAGMA index_list". There will be ** no "pk" index if the PRIMARY KEY really is an alias for the ROWID. */ - zSql = sqlite3_mprintf("SELECT 1 FROM pragma_index_list(%Q)" - " WHERE origin='pk'", zTab); - rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); - sqlite3_free(zSql); - if( rc ){ - freeColumnList(azCol); - return 0; - } - rc = sqlite3_step(pStmt); - sqlite3_finalize(pStmt); - preserveRowid = rc==SQLITE_ROW; + zSql = sqlite3_mprintf("SELECT 1 FROM pragma_index_list(%Q)" + " WHERE origin='pk'", zTab); + rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); + sqlite3_free(zSql); + if( rc ){ + freeColumnList(azCol); + return 0; } - if( preserveRowid ){ - /* Only preserve the rowid if we can find a name to use for the + rc = sqlite3_step(pStmt); + sqlite3_finalize(pStmt); + preserveRowid = rc==SQLITE_ROW; + } + if( preserveRowid ){ + /* Only preserve the rowid if we can find a name to use for the ** rowid */ - static char *azRowid[] = { "rowid", "_rowid_", "oid" }; - int i, j; - for(j=0; j<3; j++){ - for(i=1; i<=nCol; i++){ - if( sqlite3_stricmp(azRowid[j],azCol[i])==0 ) break; - } - if( i>nCol ){ - /* At this point, we know that azRowid[j] is not the name of any + static char *azRowid[] = { "rowid", "_rowid_", "oid" }; + int i, j; + for(j=0; j<3; j++){ + for(i=1; i<=nCol; i++){ + if( sqlite3_stricmp(azRowid[j],azCol[i])==0 ) break; + } + if( i>nCol ){ + /* At this point, we know that azRowid[j] is not the name of any ** ordinary column in the table. Verify that azRowid[j] is a valid ** name for the rowid before adding it to azCol[0]. WITHOUT ROWID ** tables will fail this last check */ - rc = sqlite3_table_column_metadata(p->db,0,zTab,azRowid[j],0,0,0,0,0); - if( rc==SQLITE_OK ) azCol[0] = azRowid[j]; - break; - } - } + rc = sqlite3_table_column_metadata(p->db,0,zTab,azRowid[j],0,0,0,0,0); + if( rc==SQLITE_OK ) azCol[0] = azRowid[j]; + break; + } } - return azCol; + } + return azCol; } /* ** Toggle the reverse_unordered_selects setting. */ static void toggleSelectOrder(sqlite3 *db){ - sqlite3_stmt *pStmt = 0; - int iSetting = 0; - char zStmt[100]; - sqlite3_prepare_v2(db, "PRAGMA reverse_unordered_selects", -1, &pStmt, 0); - if( sqlite3_step(pStmt)==SQLITE_ROW ){ - iSetting = sqlite3_column_int(pStmt, 0); - } - sqlite3_finalize(pStmt); - sqlite3_snprintf(sizeof(zStmt), zStmt, - "PRAGMA reverse_unordered_selects(%d)", !iSetting); - sqlite3_exec(db, zStmt, 0, 0, 0); + sqlite3_stmt *pStmt = 0; + int iSetting = 0; + char zStmt[100]; + sqlite3_prepare_v2(db, "PRAGMA reverse_unordered_selects", -1, &pStmt, 0); + if( sqlite3_step(pStmt)==SQLITE_ROW ){ + iSetting = sqlite3_column_int(pStmt, 0); + } + sqlite3_finalize(pStmt); + sqlite3_snprintf(sizeof(zStmt), zStmt, + "PRAGMA reverse_unordered_selects(%d)", !iSetting); + sqlite3_exec(db, zStmt, 0, 0, 0); } /* @@ -14856,114 +14856,114 @@ static void toggleSelectOrder(sqlite3 *db){ ** This routine should print text sufficient to recreate the table. */ static int dump_callback(void *pArg, int nArg, char **azArg, char **azNotUsed){ - int rc; - const char *zTable; - const char *zType; - const char *zSql; - ShellState *p = (ShellState *)pArg; - int dataOnly; - int noSys; - - UNUSED_PARAMETER(azNotUsed); - if( nArg!=3 || azArg==0 ) return 0; - zTable = azArg[0]; - zType = azArg[1]; - zSql = azArg[2]; - dataOnly = (p->shellFlgs & SHFLG_DumpDataOnly)!=0; - noSys = (p->shellFlgs & SHFLG_DumpNoSys)!=0; - - if( strcmp(zTable, "sqlite_sequence")==0 && !noSys ){ - if( !dataOnly ) raw_printf(p->out, "DELETE FROM sqlite_sequence;\n"); - }else if( sqlite3_strglob("sqlite_stat?", zTable)==0 && !noSys ){ - if( !dataOnly ) raw_printf(p->out, "ANALYZE sqlite_schema;\n"); - }else if( strncmp(zTable, "sqlite_", 7)==0 ){ - return 0; - }else if( dataOnly ){ - /* no-op */ - }else if( strncmp(zSql, "CREATE VIRTUAL TABLE", 20)==0 ){ - char *zIns; - if( !p->writableSchema ){ - raw_printf(p->out, "PRAGMA writable_schema=ON;\n"); - p->writableSchema = 1; - } - zIns = sqlite3_mprintf( - "INSERT INTO sqlite_schema(type,name,tbl_name,rootpage,sql)" - "VALUES('table','%q','%q',0,'%q');", - zTable, zTable, zSql); - utf8_printf(p->out, "%s\n", zIns); - sqlite3_free(zIns); - return 0; - }else{ - printSchemaLine(p->out, zSql, ";\n"); - } - - if( strcmp(zType, "table")==0 ){ - ShellText sSelect; - ShellText sTable; - char **azCol; - int i; - char *savedDestTable; - int savedMode; + int rc; + const char *zTable; + const char *zType; + const char *zSql; + ShellState *p = (ShellState *)pArg; + int dataOnly; + int noSys; + + UNUSED_PARAMETER(azNotUsed); + if( nArg!=3 || azArg==0 ) return 0; + zTable = azArg[0]; + zType = azArg[1]; + zSql = azArg[2]; + dataOnly = (p->shellFlgs & SHFLG_DumpDataOnly)!=0; + noSys = (p->shellFlgs & SHFLG_DumpNoSys)!=0; + + if( strcmp(zTable, "sqlite_sequence")==0 && !noSys ){ + if( !dataOnly ) raw_printf(p->out, "DELETE FROM sqlite_sequence;\n"); + }else if( sqlite3_strglob("sqlite_stat?", zTable)==0 && !noSys ){ + if( !dataOnly ) raw_printf(p->out, "ANALYZE sqlite_schema;\n"); + }else if( strncmp(zTable, "sqlite_", 7)==0 ){ + return 0; + }else if( dataOnly ){ + /* no-op */ + }else if( strncmp(zSql, "CREATE VIRTUAL TABLE", 20)==0 ){ + char *zIns; + if( !p->writableSchema ){ + raw_printf(p->out, "PRAGMA writable_schema=ON;\n"); + p->writableSchema = 1; + } + zIns = sqlite3_mprintf( + "INSERT INTO sqlite_schema(type,name,tbl_name,rootpage,sql)" + "VALUES('table','%q','%q',0,'%q');", + zTable, zTable, zSql); + utf8_printf(p->out, "%s\n", zIns); + sqlite3_free(zIns); + return 0; + }else{ + printSchemaLine(p->out, zSql, ";\n"); + } + + if( strcmp(zType, "table")==0 ){ + ShellText sSelect; + ShellText sTable; + char **azCol; + int i; + char *savedDestTable; + int savedMode; - azCol = tableColumnList(p, zTable); - if( azCol==0 ){ - p->nErr++; - return 0; - } + azCol = tableColumnList(p, zTable); + if( azCol==0 ){ + p->nErr++; + return 0; + } - /* Always quote the table name, even if it appears to be pure ascii, + /* Always quote the table name, even if it appears to be pure ascii, ** in case it is a keyword. Ex: INSERT INTO "table" ... */ - initText(&sTable); - appendText(&sTable, zTable, quoteChar(zTable)); - /* If preserving the rowid, add a column list after the table name. + initText(&sTable); + appendText(&sTable, zTable, quoteChar(zTable)); + /* If preserving the rowid, add a column list after the table name. ** In other words: "INSERT INTO tab(rowid,a,b,c,...) VALUES(...)" ** instead of the usual "INSERT INTO tab VALUES(...)". */ - if( azCol[0] ){ - appendText(&sTable, "(", 0); - appendText(&sTable, azCol[0], 0); - for(i=1; azCol[i]; i++){ - appendText(&sTable, ",", 0); - appendText(&sTable, azCol[i], quoteChar(azCol[i])); - } - appendText(&sTable, ")", 0); - } - - /* Build an appropriate SELECT statement */ - initText(&sSelect); - appendText(&sSelect, "SELECT ", 0); - if( azCol[0] ){ - appendText(&sSelect, azCol[0], 0); - appendText(&sSelect, ",", 0); - } - for(i=1; azCol[i]; i++){ - appendText(&sSelect, azCol[i], quoteChar(azCol[i])); - if( azCol[i+1] ){ - appendText(&sSelect, ",", 0); - } - } - freeColumnList(azCol); - appendText(&sSelect, " FROM ", 0); - appendText(&sSelect, zTable, quoteChar(zTable)); - - savedDestTable = p->zDestTable; - savedMode = p->mode; - p->zDestTable = sTable.z; - p->mode = p->cMode = MODE_Insert; - rc = shell_exec(p, sSelect.z, 0); - if( (rc&0xff)==SQLITE_CORRUPT ){ - raw_printf(p->out, "/****** CORRUPTION ERROR *******/\n"); - toggleSelectOrder(p->db); - shell_exec(p, sSelect.z, 0); - toggleSelectOrder(p->db); - } - p->zDestTable = savedDestTable; - p->mode = savedMode; - freeText(&sTable); - freeText(&sSelect); - if( rc ) p->nErr++; + if( azCol[0] ){ + appendText(&sTable, "(", 0); + appendText(&sTable, azCol[0], 0); + for(i=1; azCol[i]; i++){ + appendText(&sTable, ",", 0); + appendText(&sTable, azCol[i], quoteChar(azCol[i])); + } + appendText(&sTable, ")", 0); + } + + /* Build an appropriate SELECT statement */ + initText(&sSelect); + appendText(&sSelect, "SELECT ", 0); + if( azCol[0] ){ + appendText(&sSelect, azCol[0], 0); + appendText(&sSelect, ",", 0); } - return 0; + for(i=1; azCol[i]; i++){ + appendText(&sSelect, azCol[i], quoteChar(azCol[i])); + if( azCol[i+1] ){ + appendText(&sSelect, ",", 0); + } + } + freeColumnList(azCol); + appendText(&sSelect, " FROM ", 0); + appendText(&sSelect, zTable, quoteChar(zTable)); + + savedDestTable = p->zDestTable; + savedMode = p->mode; + p->zDestTable = sTable.z; + p->mode = p->cMode = MODE_Insert; + rc = shell_exec(p, sSelect.z, 0); + if( (rc&0xff)==SQLITE_CORRUPT ){ + raw_printf(p->out, "/****** CORRUPTION ERROR *******/\n"); + toggleSelectOrder(p->db); + shell_exec(p, sSelect.z, 0); + toggleSelectOrder(p->db); + } + p->zDestTable = savedDestTable; + p->mode = savedMode; + freeText(&sTable); + freeText(&sSelect); + if( rc ) p->nErr++; + } + return 0; } /* @@ -14974,34 +14974,34 @@ static int dump_callback(void *pArg, int nArg, char **azArg, char **azNotUsed){ ** "ORDER BY rowid DESC" to the end. */ static int run_schema_dump_query( - ShellState *p, - const char *zQuery + ShellState *p, + const char *zQuery ){ - int rc; - char *zErr = 0; - rc = sqlite3_exec(p->db, zQuery, dump_callback, p, &zErr); - if( rc==SQLITE_CORRUPT ){ - char *zQ2; - int len = strlen30(zQuery); - raw_printf(p->out, "/****** CORRUPTION ERROR *******/\n"); - if( zErr ){ - utf8_printf(p->out, "/****** %s ******/\n", zErr); - sqlite3_free(zErr); - zErr = 0; - } - zQ2 = malloc( len+100 ); - if( zQ2==0 ) return rc; - sqlite3_snprintf(len+100, zQ2, "%s ORDER BY rowid DESC", zQuery); - rc = sqlite3_exec(p->db, zQ2, dump_callback, p, &zErr); - if( rc ){ - utf8_printf(p->out, "/****** ERROR: %s ******/\n", zErr); - }else{ - rc = SQLITE_CORRUPT; - } - sqlite3_free(zErr); - free(zQ2); + int rc; + char *zErr = 0; + rc = sqlite3_exec(p->db, zQuery, dump_callback, p, &zErr); + if( rc==SQLITE_CORRUPT ){ + char *zQ2; + int len = strlen30(zQuery); + raw_printf(p->out, "/****** CORRUPTION ERROR *******/\n"); + if( zErr ){ + utf8_printf(p->out, "/****** %s ******/\n", zErr); + sqlite3_free(zErr); + zErr = 0; + } + zQ2 = malloc( len+100 ); + if( zQ2==0 ) return rc; + sqlite3_snprintf(len+100, zQ2, "%s ORDER BY rowid DESC", zQuery); + rc = sqlite3_exec(p->db, zQ2, dump_callback, p, &zErr); + if( rc ){ + utf8_printf(p->out, "/****** ERROR: %s ******/\n", zErr); + }else{ + rc = SQLITE_CORRUPT; } - return rc; + sqlite3_free(zErr); + free(zQ2); + } + return rc; } /* @@ -15015,249 +15015,249 @@ static int run_schema_dump_query( */ static const char *(azHelp[]) = { #if defined(SQLITE_HAVE_ZLIB) && !defined(SQLITE_OMIT_VIRTUALTABLE) - ".archive ... Manage SQL archives", - " Each command must have exactly one of the following options:", - " -c, --create Create a new archive", - " -u, --update Add or update files with changed mtime", - " -i, --insert Like -u but always add even if unchanged", - " -r, --remove Remove files from archive", - " -t, --list List contents of archive", - " -x, --extract Extract files from archive", - " Optional arguments:", - " -v, --verbose Print each filename as it is processed", - " -f FILE, --file FILE Use archive FILE (default is current db)", - " -a FILE, --append FILE Open FILE using the apndvfs VFS", - " -C DIR, --directory DIR Read/extract files from directory DIR", - " -g, --glob Use glob matching for names in archive", - " -n, --dryrun Show the SQL that would have occurred", - " Examples:", - " .ar -cf ARCHIVE foo bar # Create ARCHIVE from files foo and bar", - " .ar -tf ARCHIVE # List members of ARCHIVE", - " .ar -xvf ARCHIVE # Verbosely extract files from ARCHIVE", - " See also:", - " http://sqlite.org/cli.html#sqlite_archive_support", + ".archive ... Manage SQL archives", + " Each command must have exactly one of the following options:", + " -c, --create Create a new archive", + " -u, --update Add or update files with changed mtime", + " -i, --insert Like -u but always add even if unchanged", + " -r, --remove Remove files from archive", + " -t, --list List contents of archive", + " -x, --extract Extract files from archive", + " Optional arguments:", + " -v, --verbose Print each filename as it is processed", + " -f FILE, --file FILE Use archive FILE (default is current db)", + " -a FILE, --append FILE Open FILE using the apndvfs VFS", + " -C DIR, --directory DIR Read/extract files from directory DIR", + " -g, --glob Use glob matching for names in archive", + " -n, --dryrun Show the SQL that would have occurred", + " Examples:", + " .ar -cf ARCHIVE foo bar # Create ARCHIVE from files foo and bar", + " .ar -tf ARCHIVE # List members of ARCHIVE", + " .ar -xvf ARCHIVE # Verbosely extract files from ARCHIVE", + " See also:", + " http://sqlite.org/cli.html#sqlite_archive_support", #endif #ifndef SQLITE_OMIT_AUTHORIZATION - ".auth ON|OFF Show authorizer callbacks", + ".auth ON|OFF Show authorizer callbacks", #endif - ".backup ?DB? FILE Backup DB (default \"main\") to FILE", - " --append Use the appendvfs", - " --async Write to FILE without journal and fsync()", - ".bail on|off Stop after hitting an error. Default OFF", - ".binary on|off Turn binary output on or off. Default OFF", - ".cd DIRECTORY Change the working directory to DIRECTORY", - ".changes on|off Show number of rows changed by SQL", - ".check GLOB Fail if output since .testcase does not match", - ".clone NEWDB Clone data into NEWDB from the existing database", - ".connection [close] [#] Open or close an auxiliary database connection", - ".databases List names and files of attached databases", - ".dbconfig ?op? ?val? List or change sqlite3_db_config() options", - ".dbinfo ?DB? Show status information about the database", - ".dump ?OBJECTS? Render database content as SQL", - " Options:", - " --data-only Output only INSERT statements", - " --newlines Allow unescaped newline characters in output", - " --nosys Omit system tables (ex: \"sqlite_stat1\")", - " --preserve-rowids Include ROWID values in the output", - " OBJECTS is a LIKE pattern for tables, indexes, triggers or views to dump", - " Additional LIKE patterns can be given in subsequent arguments", - ".echo on|off Turn command echo on or off", - ".eqp on|off|full|... Enable or disable automatic EXPLAIN QUERY PLAN", - " Other Modes:", + ".backup ?DB? FILE Backup DB (default \"main\") to FILE", + " --append Use the appendvfs", + " --async Write to FILE without journal and fsync()", + ".bail on|off Stop after hitting an error. Default OFF", + ".binary on|off Turn binary output on or off. Default OFF", + ".cd DIRECTORY Change the working directory to DIRECTORY", + ".changes on|off Show number of rows changed by SQL", + ".check GLOB Fail if output since .testcase does not match", + ".clone NEWDB Clone data into NEWDB from the existing database", + ".connection [close] [#] Open or close an auxiliary database connection", + ".databases List names and files of attached databases", + ".dbconfig ?op? ?val? List or change sqlite3_db_config() options", + ".dbinfo ?DB? Show status information about the database", + ".dump ?OBJECTS? Render database content as SQL", + " Options:", + " --data-only Output only INSERT statements", + " --newlines Allow unescaped newline characters in output", + " --nosys Omit system tables (ex: \"sqlite_stat1\")", + " --preserve-rowids Include ROWID values in the output", + " OBJECTS is a LIKE pattern for tables, indexes, triggers or views to dump", + " Additional LIKE patterns can be given in subsequent arguments", + ".echo on|off Turn command echo on or off", + ".eqp on|off|full|... Enable or disable automatic EXPLAIN QUERY PLAN", + " Other Modes:", #ifdef SQLITE_DEBUG - " test Show raw EXPLAIN QUERY PLAN output", - " trace Like \"full\" but enable \"PRAGMA vdbe_trace\"", + " test Show raw EXPLAIN QUERY PLAN output", + " trace Like \"full\" but enable \"PRAGMA vdbe_trace\"", #endif - " trigger Like \"full\" but also show trigger bytecode", - ".excel Display the output of next command in spreadsheet", - " --bom Put a UTF8 byte-order mark on intermediate file", - ".exit ?CODE? Exit this program with return-code CODE", - ".expert EXPERIMENTAL. Suggest indexes for queries", - ".explain ?on|off|auto? Change the EXPLAIN formatting mode. Default: auto", - ".filectrl CMD ... Run various sqlite3_file_control() operations", - " --schema SCHEMA Use SCHEMA instead of \"main\"", - " --help Show CMD details", - ".fullschema ?--indent? Show schema and the content of sqlite_stat tables", - ".headers on|off Turn display of headers on or off", - ".help ?-all? ?PATTERN? Show help text for PATTERN", - ".import FILE TABLE Import data from FILE into TABLE", - " Options:", - " --ascii Use \\037 and \\036 as column and row separators", - " --csv Use , and \\n as column and row separators", - " --skip N Skip the first N rows of input", - " -v \"Verbose\" - increase auxiliary output", - " Notes:", - " * If TABLE does not exist, it is created. The first row of input", - " determines the column names.", - " * If neither --csv or --ascii are used, the input mode is derived", - " from the \".mode\" output mode", - " * If FILE begins with \"|\" then it is a command that generates the", - " input text.", + " trigger Like \"full\" but also show trigger bytecode", + ".excel Display the output of next command in spreadsheet", + " --bom Put a UTF8 byte-order mark on intermediate file", + ".exit ?CODE? Exit this program with return-code CODE", + ".expert EXPERIMENTAL. Suggest indexes for queries", + ".explain ?on|off|auto? Change the EXPLAIN formatting mode. Default: auto", + ".filectrl CMD ... Run various sqlite3_file_control() operations", + " --schema SCHEMA Use SCHEMA instead of \"main\"", + " --help Show CMD details", + ".fullschema ?--indent? Show schema and the content of sqlite_stat tables", + ".headers on|off Turn display of headers on or off", + ".help ?-all? ?PATTERN? Show help text for PATTERN", + ".import FILE TABLE Import data from FILE into TABLE", + " Options:", + " --ascii Use \\037 and \\036 as column and row separators", + " --csv Use , and \\n as column and row separators", + " --skip N Skip the first N rows of input", + " -v \"Verbose\" - increase auxiliary output", + " Notes:", + " * If TABLE does not exist, it is created. The first row of input", + " determines the column names.", + " * If neither --csv or --ascii are used, the input mode is derived", + " from the \".mode\" output mode", + " * If FILE begins with \"|\" then it is a command that generates the", + " input text.", #ifndef SQLITE_OMIT_TEST_CONTROL - ".imposter INDEX TABLE Create imposter table TABLE on index INDEX", + ".imposter INDEX TABLE Create imposter table TABLE on index INDEX", #endif - ".indexes ?TABLE? Show names of indexes", - " If TABLE is specified, only show indexes for", - " tables matching TABLE using the LIKE operator.", + ".indexes ?TABLE? Show names of indexes", + " If TABLE is specified, only show indexes for", + " tables matching TABLE using the LIKE operator.", #ifdef SQLITE_ENABLE_IOTRACE - ".iotrace FILE Enable I/O diagnostic logging to FILE", + ".iotrace FILE Enable I/O diagnostic logging to FILE", #endif - ".limit ?LIMIT? ?VAL? Display or change the value of an SQLITE_LIMIT", - ".lint OPTIONS Report potential schema issues.", - " Options:", - " fkey-indexes Find missing foreign key indexes", + ".limit ?LIMIT? ?VAL? Display or change the value of an SQLITE_LIMIT", + ".lint OPTIONS Report potential schema issues.", + " Options:", + " fkey-indexes Find missing foreign key indexes", #ifndef SQLITE_OMIT_LOAD_EXTENSION - ".load FILE ?ENTRY? Load an extension library", + ".load FILE ?ENTRY? Load an extension library", #endif - ".log FILE|off Turn logging on or off. FILE can be stderr/stdout", - ".mode MODE ?TABLE? Set output mode", - " MODE is one of:", - " ascii Columns/rows delimited by 0x1F and 0x1E", - " box Tables using unicode box-drawing characters", - " csv Comma-separated values", - " column Output in columns. (See .width)", - " html HTML
"); + output_html_string(p->out, azCol[i]); + raw_printf(p->out,"
"); + output_html_string(p->out, azArg[i] ? azArg[i] : p->nullValue); + raw_printf(p->out,"
"); - output_html_string(p->out, azCol[i]); - raw_printf(p->out,"
"); - output_html_string(p->out, azArg[i] ? azArg[i] : p->nullValue); - raw_printf(p->out,"
code", - " insert SQL insert statements for TABLE", - " json Results in a JSON array", - " line One value per line", - " list Values delimited by \"|\"", - " markdown Markdown table format", - " quote Escape answers as for SQL", - " table ASCII-art table", - " tabs Tab-separated values", - " tcl TCL list elements", - ".nonce STRING Disable safe mode for one command if the nonce matches", - ".nullvalue STRING Use STRING in place of NULL values", - ".once ?OPTIONS? ?FILE? Output for the next SQL command only to FILE", - " If FILE begins with '|' then open as a pipe", - " --bom Put a UTF8 byte-order mark at the beginning", - " -e Send output to the system text editor", - " -x Send output as CSV to a spreadsheet (same as \".excel\")", + ".log FILE|off Turn logging on or off. FILE can be stderr/stdout", + ".mode MODE ?TABLE? Set output mode", + " MODE is one of:", + " ascii Columns/rows delimited by 0x1F and 0x1E", + " box Tables using unicode box-drawing characters", + " csv Comma-separated values", + " column Output in columns. (See .width)", + " html HTML
code", + " insert SQL insert statements for TABLE", + " json Results in a JSON array", + " line One value per line", + " list Values delimited by \"|\"", + " markdown Markdown table format", + " quote Escape answers as for SQL", + " table ASCII-art table", + " tabs Tab-separated values", + " tcl TCL list elements", + ".nonce STRING Disable safe mode for one command if the nonce matches", + ".nullvalue STRING Use STRING in place of NULL values", + ".once ?OPTIONS? ?FILE? Output for the next SQL command only to FILE", + " If FILE begins with '|' then open as a pipe", + " --bom Put a UTF8 byte-order mark at the beginning", + " -e Send output to the system text editor", + " -x Send output as CSV to a spreadsheet (same as \".excel\")", #ifdef SQLITE_DEBUG - ".oom ?--repeat M? ?N? Simulate an OOM error on the N-th allocation", -#endif - ".open ?OPTIONS? ?FILE? Close existing database and reopen FILE", - " Options:", - " --append Use appendvfs to append database to the end of FILE", + ".oom ?--repeat M? ?N? Simulate an OOM error on the N-th allocation", +#endif + ".open ?OPTIONS? ?FILE? Close existing database and reopen FILE", + " Options:", + " --append Use appendvfs to append database to the end of FILE", #ifndef SQLITE_OMIT_DESERIALIZE - " --deserialize Load into memory using sqlite3_deserialize()", - " --hexdb Load the output of \"dbtotxt\" as an in-memory db", - " --maxsize N Maximum size for --hexdb or --deserialized database", + " --deserialize Load into memory using sqlite3_deserialize()", + " --hexdb Load the output of \"dbtotxt\" as an in-memory db", + " --maxsize N Maximum size for --hexdb or --deserialized database", #endif - " --new Initialize FILE to an empty database", - " --nofollow Do not follow symbolic links", - " --readonly Open FILE readonly", - " --zip FILE is a ZIP archive", - ".output ?FILE? Send output to FILE or stdout if FILE is omitted", - " If FILE begins with '|' then open it as a pipe.", - " Options:", - " --bom Prefix output with a UTF8 byte-order mark", - " -e Send output to the system text editor", - " -x Send output as CSV to a spreadsheet", - ".parameter CMD ... Manage SQL parameter bindings", - " clear Erase all bindings", - " init Initialize the TEMP table that holds bindings", - " list List the current parameter bindings", - " set PARAMETER VALUE Given SQL parameter PARAMETER a value of VALUE", - " PARAMETER should start with one of: $ : @ ?", - " unset PARAMETER Remove PARAMETER from the binding table", - ".print STRING... Print literal STRING", + " --new Initialize FILE to an empty database", + " --nofollow Do not follow symbolic links", + " --readonly Open FILE readonly", + " --zip FILE is a ZIP archive", + ".output ?FILE? Send output to FILE or stdout if FILE is omitted", + " If FILE begins with '|' then open it as a pipe.", + " Options:", + " --bom Prefix output with a UTF8 byte-order mark", + " -e Send output to the system text editor", + " -x Send output as CSV to a spreadsheet", + ".parameter CMD ... Manage SQL parameter bindings", + " clear Erase all bindings", + " init Initialize the TEMP table that holds bindings", + " list List the current parameter bindings", + " set PARAMETER VALUE Given SQL parameter PARAMETER a value of VALUE", + " PARAMETER should start with one of: $ : @ ?", + " unset PARAMETER Remove PARAMETER from the binding table", + ".print STRING... Print literal STRING", #ifndef SQLITE_OMIT_PROGRESS_CALLBACK - ".progress N Invoke progress handler after every N opcodes", - " --limit N Interrupt after N progress callbacks", - " --once Do no more than one progress interrupt", - " --quiet|-q No output except at interrupts", - " --reset Reset the count for each input and interrupt", + ".progress N Invoke progress handler after every N opcodes", + " --limit N Interrupt after N progress callbacks", + " --once Do no more than one progress interrupt", + " --quiet|-q No output except at interrupts", + " --reset Reset the count for each input and interrupt", #endif - ".prompt MAIN CONTINUE Replace the standard prompts", - ".quit Exit this program", - ".read FILE Read input from FILE", + ".prompt MAIN CONTINUE Replace the standard prompts", + ".quit Exit this program", + ".read FILE Read input from FILE", #if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB) - ".recover Recover as much data as possible from corrupt db.", - " --freelist-corrupt Assume the freelist is corrupt", - " --recovery-db NAME Store recovery metadata in database file NAME", - " --lost-and-found TABLE Alternative name for the lost-and-found table", - " --no-rowids Do not attempt to recover rowid values", - " that are not also INTEGER PRIMARY KEYs", + ".recover Recover as much data as possible from corrupt db.", + " --freelist-corrupt Assume the freelist is corrupt", + " --recovery-db NAME Store recovery metadata in database file NAME", + " --lost-and-found TABLE Alternative name for the lost-and-found table", + " --no-rowids Do not attempt to recover rowid values", + " that are not also INTEGER PRIMARY KEYs", #endif - ".restore ?DB? FILE Restore content of DB (default \"main\") from FILE", - ".save FILE Write in-memory database into FILE", - ".scanstats on|off Turn sqlite3_stmt_scanstatus() metrics on or off", - ".schema ?PATTERN? Show the CREATE statements matching PATTERN", - " Options:", - " --indent Try to pretty-print the schema", - " --nosys Omit objects whose names start with \"sqlite_\"", - ".selftest ?OPTIONS? Run tests defined in the SELFTEST table", - " Options:", - " --init Create a new SELFTEST table", - " -v Verbose output", - ".separator COL ?ROW? Change the column and row separators", + ".restore ?DB? FILE Restore content of DB (default \"main\") from FILE", + ".save FILE Write in-memory database into FILE", + ".scanstats on|off Turn sqlite3_stmt_scanstatus() metrics on or off", + ".schema ?PATTERN? Show the CREATE statements matching PATTERN", + " Options:", + " --indent Try to pretty-print the schema", + " --nosys Omit objects whose names start with \"sqlite_\"", + ".selftest ?OPTIONS? Run tests defined in the SELFTEST table", + " Options:", + " --init Create a new SELFTEST table", + " -v Verbose output", + ".separator COL ?ROW? Change the column and row separators", #if defined(SQLITE_ENABLE_SESSION) - ".session ?NAME? CMD ... Create or control sessions", - " Subcommands:", - " attach TABLE Attach TABLE", - " changeset FILE Write a changeset into FILE", - " close Close one session", - " enable ?BOOLEAN? Set or query the enable bit", - " filter GLOB... Reject tables matching GLOBs", - " indirect ?BOOLEAN? Mark or query the indirect status", - " isempty Query whether the session is empty", - " list List currently open session names", - " open DB NAME Open a new session on DB", - " patchset FILE Write a patchset into FILE", - " If ?NAME? is omitted, the first defined session is used.", + ".session ?NAME? CMD ... Create or control sessions", + " Subcommands:", + " attach TABLE Attach TABLE", + " changeset FILE Write a changeset into FILE", + " close Close one session", + " enable ?BOOLEAN? Set or query the enable bit", + " filter GLOB... Reject tables matching GLOBs", + " indirect ?BOOLEAN? Mark or query the indirect status", + " isempty Query whether the session is empty", + " list List currently open session names", + " open DB NAME Open a new session on DB", + " patchset FILE Write a patchset into FILE", + " If ?NAME? is omitted, the first defined session is used.", #endif - ".sha3sum ... Compute a SHA3 hash of database content", - " Options:", - " --schema Also hash the sqlite_schema table", - " --sha3-224 Use the sha3-224 algorithm", - " --sha3-256 Use the sha3-256 algorithm (default)", - " --sha3-384 Use the sha3-384 algorithm", - " --sha3-512 Use the sha3-512 algorithm", - " Any other argument is a LIKE pattern for tables to hash", + ".sha3sum ... Compute a SHA3 hash of database content", + " Options:", + " --schema Also hash the sqlite_schema table", + " --sha3-224 Use the sha3-224 algorithm", + " --sha3-256 Use the sha3-256 algorithm (default)", + " --sha3-384 Use the sha3-384 algorithm", + " --sha3-512 Use the sha3-512 algorithm", + " Any other argument is a LIKE pattern for tables to hash", #ifndef SQLITE_NOHAVE_SYSTEM - ".shell CMD ARGS... Run CMD ARGS... in a system shell", + ".shell CMD ARGS... Run CMD ARGS... in a system shell", #endif - ".show Show the current values for various settings", - ".stats ?ARG? Show stats or turn stats on or off", - " off Turn off automatic stat display", - " on Turn on automatic stat display", - " stmt Show statement stats", - " vmstep Show the virtual machine step count only", + ".show Show the current values for various settings", + ".stats ?ARG? Show stats or turn stats on or off", + " off Turn off automatic stat display", + " on Turn on automatic stat display", + " stmt Show statement stats", + " vmstep Show the virtual machine step count only", #ifndef SQLITE_NOHAVE_SYSTEM - ".system CMD ARGS... Run CMD ARGS... in a system shell", + ".system CMD ARGS... Run CMD ARGS... in a system shell", #endif - ".tables ?TABLE? List names of tables matching LIKE pattern TABLE", - ".testcase NAME Begin redirecting output to 'testcase-out.txt'", - ".testctrl CMD ... Run various sqlite3_test_control() operations", - " Run \".testctrl\" with no arguments for details", - ".timeout MS Try opening locked tables for MS milliseconds", - ".timer on|off Turn SQL timer on or off", + ".tables ?TABLE? List names of tables matching LIKE pattern TABLE", + ".testcase NAME Begin redirecting output to 'testcase-out.txt'", + ".testctrl CMD ... Run various sqlite3_test_control() operations", + " Run \".testctrl\" with no arguments for details", + ".timeout MS Try opening locked tables for MS milliseconds", + ".timer on|off Turn SQL timer on or off", #ifndef SQLITE_OMIT_TRACE - ".trace ?OPTIONS? Output each SQL statement as it is run", - " FILE Send output to FILE", - " stdout Send output to stdout", - " stderr Send output to stderr", - " off Disable tracing", - " --expanded Expand query parameters", + ".trace ?OPTIONS? Output each SQL statement as it is run", + " FILE Send output to FILE", + " stdout Send output to stdout", + " stderr Send output to stderr", + " off Disable tracing", + " --expanded Expand query parameters", #ifdef SQLITE_ENABLE_NORMALIZE - " --normalized Normal the SQL statements", + " --normalized Normal the SQL statements", #endif - " --plain Show SQL as it is input", - " --stmt Trace statement execution (SQLITE_TRACE_STMT)", - " --profile Profile statements (SQLITE_TRACE_PROFILE)", - " --row Trace each row (SQLITE_TRACE_ROW)", - " --close Trace connection close (SQLITE_TRACE_CLOSE)", + " --plain Show SQL as it is input", + " --stmt Trace statement execution (SQLITE_TRACE_STMT)", + " --profile Profile statements (SQLITE_TRACE_PROFILE)", + " --row Trace each row (SQLITE_TRACE_ROW)", + " --close Trace connection close (SQLITE_TRACE_CLOSE)", #endif /* SQLITE_OMIT_TRACE */ #ifdef SQLITE_DEBUG - ".unmodule NAME ... Unregister virtual table modules", - " --allexcept Unregister everything except those named", + ".unmodule NAME ... Unregister virtual table modules", + " --allexcept Unregister everything except those named", #endif - ".vfsinfo ?AUX? Information about the top-level VFS", - ".vfslist List all available VFSes", - ".vfsname ?AUX? Print the name of the VFS stack", - ".width NUM1 NUM2 ... Set minimum column widths for columnar output", - " Negative values right-justify", + ".vfsinfo ?AUX? Information about the top-level VFS", + ".vfslist List all available VFSes", + ".vfsname ?AUX? Print the name of the VFS stack", + ".width NUM1 NUM2 ... Set minimum column widths for columnar output", + " Negative values right-justify", }; /* @@ -15270,64 +15270,64 @@ static const char *(azHelp[]) = { ** Return the number of matches. */ static int showHelp(FILE *out, const char *zPattern){ - int i = 0; - int j = 0; - int n = 0; - char *zPat; - if( zPattern==0 - || zPattern[0]=='0' - || strcmp(zPattern,"-a")==0 - || strcmp(zPattern,"-all")==0 - || strcmp(zPattern,"--all")==0 - ){ - /* Show all commands, but only one line per command */ - if( zPattern==0 ) zPattern = ""; - for(i=0; ip); - sqlite3_free(pSession->zName); - for(i=0; inFilter; i++){ - sqlite3_free(pSession->azFilter[i]); - } - sqlite3_free(pSession->azFilter); - memset(pSession, 0, sizeof(OpenSession)); + int i; + sqlite3session_delete(pSession->p); + sqlite3_free(pSession->zName); + for(i=0; inFilter; i++){ + sqlite3_free(pSession->azFilter[i]); + } + sqlite3_free(pSession->azFilter); + memset(pSession, 0, sizeof(OpenSession)); } #endif @@ -15392,12 +15392,12 @@ static void session_close(OpenSession *pSession){ */ #if defined(SQLITE_ENABLE_SESSION) static void session_close_all(ShellState *p, int i){ - int j; - struct AuxDb *pAuxDb = i<0 ? p->pAuxDb : &p->aAuxDb[i]; - for(j=0; jnSession; j++){ - session_close(&pAuxDb->aSession[j]); - } - pAuxDb->nSession = 0; + int j; + struct AuxDb *pAuxDb = i<0 ? p->pAuxDb : &p->aAuxDb[i]; + for(j=0; jnSession; j++){ + session_close(&pAuxDb->aSession[j]); + } + pAuxDb->nSession = 0; } #else # define session_close_all(X,Y) @@ -15409,12 +15409,12 @@ static void session_close_all(ShellState *p, int i){ */ #if defined(SQLITE_ENABLE_SESSION) static int session_filter(void *pCtx, const char *zTab){ - OpenSession *pSession = (OpenSession*)pCtx; - int i; - for(i=0; inFilter; i++){ - if( sqlite3_strglob(pSession->azFilter[i], zTab)==0 ) return 0; - } - return 1; + OpenSession *pSession = (OpenSession*)pCtx; + int i; + for(i=0; inFilter; i++){ + if( sqlite3_strglob(pSession->azFilter[i], zTab)==0 ) return 0; + } + return 1; } #endif @@ -15428,38 +15428,38 @@ static int session_filter(void *pCtx, const char *zTab){ ** the type cannot be determined from content. */ int deduceDatabaseType(const char *zName, int dfltZip){ - FILE *f = fopen(zName, "rb"); - size_t n; - int rc = SHELL_OPEN_UNSPEC; - char zBuf[100]; - if( f==0 ){ - if( dfltZip && sqlite3_strlike("%.zip",zName,0)==0 ){ - return SHELL_OPEN_ZIPFILE; - }else{ - return SHELL_OPEN_NORMAL; - } - } - n = fread(zBuf, 16, 1, f); - if( n==1 && memcmp(zBuf, "SQLite format 3", 16)==0 ){ - fclose(f); - return SHELL_OPEN_NORMAL; - } - fseek(f, -25, SEEK_END); - n = fread(zBuf, 25, 1, f); - if( n==1 && memcmp(zBuf, "Start-Of-SQLite3-", 17)==0 ){ - rc = SHELL_OPEN_APPENDVFS; + FILE *f = fopen(zName, "rb"); + size_t n; + int rc = SHELL_OPEN_UNSPEC; + char zBuf[100]; + if( f==0 ){ + if( dfltZip && sqlite3_strlike("%.zip",zName,0)==0 ){ + return SHELL_OPEN_ZIPFILE; }else{ - fseek(f, -22, SEEK_END); - n = fread(zBuf, 22, 1, f); - if( n==1 && zBuf[0]==0x50 && zBuf[1]==0x4b && zBuf[2]==0x05 - && zBuf[3]==0x06 ){ - rc = SHELL_OPEN_ZIPFILE; - }else if( n==0 && dfltZip && sqlite3_strlike("%.zip",zName,0)==0 ){ - rc = SHELL_OPEN_ZIPFILE; - } + return SHELL_OPEN_NORMAL; } + } + n = fread(zBuf, 16, 1, f); + if( n==1 && memcmp(zBuf, "SQLite format 3", 16)==0 ){ fclose(f); - return rc; + return SHELL_OPEN_NORMAL; + } + fseek(f, -25, SEEK_END); + n = fread(zBuf, 25, 1, f); + if( n==1 && memcmp(zBuf, "Start-Of-SQLite3-", 17)==0 ){ + rc = SHELL_OPEN_APPENDVFS; + }else{ + fseek(f, -22, SEEK_END); + n = fread(zBuf, 22, 1, f); + if( n==1 && zBuf[0]==0x50 && zBuf[1]==0x4b && zBuf[2]==0x05 + && zBuf[3]==0x06 ){ + rc = SHELL_OPEN_ZIPFILE; + }else if( n==0 && dfltZip && sqlite3_strlike("%.zip",zName,0)==0 ){ + rc = SHELL_OPEN_ZIPFILE; + } + } + fclose(f); + return rc; } #ifndef SQLITE_OMIT_DESERIALIZE @@ -15469,88 +15469,88 @@ int deduceDatabaseType(const char *zName, int dfltZip){ ** If p->aAuxDb[].zDbFilename is 0, then read from standard input. */ static unsigned char *readHexDb(ShellState *p, int *pnData){ - unsigned char *a = 0; - int nLine; - int n = 0; - int pgsz = 0; - int iOffset = 0; - int j, k; - int rc; - FILE *in; - const char *zDbFilename = p->pAuxDb->zDbFilename; - unsigned int x[16]; - char zLine[1000]; - if( zDbFilename ){ - in = fopen(zDbFilename, "r"); - if( in==0 ){ - utf8_printf(stderr, "cannot open \"%s\" for reading\n", zDbFilename); - return 0; - } - nLine = 0; - }else{ - in = p->in; - nLine = p->lineno; - if( in==0 ) in = stdin; - } - *pnData = 0; - nLine++; - if( fgets(zLine, sizeof(zLine), in)==0 ) goto readHexDb_error; - rc = sscanf(zLine, "| size %d pagesize %d", &n, &pgsz); - if( rc!=2 ) goto readHexDb_error; - if( n<0 ) goto readHexDb_error; - if( pgsz<512 || pgsz>65536 || (pgsz&(pgsz-1))!=0 ) goto readHexDb_error; - n = (n+pgsz-1)&~(pgsz-1); /* Round n up to the next multiple of pgsz */ - a = sqlite3_malloc( n ? n : 1 ); - if( a==0 ){ - utf8_printf(stderr, "Out of memory!\n"); - goto readHexDb_error; - } - memset(a, 0, n); - if( pgsz<512 || pgsz>65536 || (pgsz & (pgsz-1))!=0 ){ - utf8_printf(stderr, "invalid pagesize\n"); - goto readHexDb_error; - } - for(nLine++; fgets(zLine, sizeof(zLine), in)!=0; nLine++){ - rc = sscanf(zLine, "| page %d offset %d", &j, &k); - if( rc==2 ){ - iOffset = k; - continue; - } - if( strncmp(zLine, "| end ", 6)==0 ){ - break; - } - rc = sscanf(zLine,"| %d: %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x", - &j, &x[0], &x[1], &x[2], &x[3], &x[4], &x[5], &x[6], &x[7], - &x[8], &x[9], &x[10], &x[11], &x[12], &x[13], &x[14], &x[15]); - if( rc==17 ){ - k = iOffset+j; - if( k+16<=n && k>=0 ){ - int ii; - for(ii=0; ii<16; ii++) a[k+ii] = x[ii]&0xff; - } - } - } - *pnData = n; - if( in!=p->in ){ - fclose(in); - }else{ - p->lineno = nLine; - } - return a; + unsigned char *a = 0; + int nLine; + int n = 0; + int pgsz = 0; + int iOffset = 0; + int j, k; + int rc; + FILE *in; + const char *zDbFilename = p->pAuxDb->zDbFilename; + unsigned int x[16]; + char zLine[1000]; + if( zDbFilename ){ + in = fopen(zDbFilename, "r"); + if( in==0 ){ + utf8_printf(stderr, "cannot open \"%s\" for reading\n", zDbFilename); + return 0; + } + nLine = 0; + }else{ + in = p->in; + nLine = p->lineno; + if( in==0 ) in = stdin; + } + *pnData = 0; + nLine++; + if( fgets(zLine, sizeof(zLine), in)==0 ) goto readHexDb_error; + rc = sscanf(zLine, "| size %d pagesize %d", &n, &pgsz); + if( rc!=2 ) goto readHexDb_error; + if( n<0 ) goto readHexDb_error; + if( pgsz<512 || pgsz>65536 || (pgsz&(pgsz-1))!=0 ) goto readHexDb_error; + n = (n+pgsz-1)&~(pgsz-1); /* Round n up to the next multiple of pgsz */ + a = sqlite3_malloc( n ? n : 1 ); + if( a==0 ){ + utf8_printf(stderr, "Out of memory!\n"); + goto readHexDb_error; + } + memset(a, 0, n); + if( pgsz<512 || pgsz>65536 || (pgsz & (pgsz-1))!=0 ){ + utf8_printf(stderr, "invalid pagesize\n"); + goto readHexDb_error; + } + for(nLine++; fgets(zLine, sizeof(zLine), in)!=0; nLine++){ + rc = sscanf(zLine, "| page %d offset %d", &j, &k); + if( rc==2 ){ + iOffset = k; + continue; + } + if( strncmp(zLine, "| end ", 6)==0 ){ + break; + } + rc = sscanf(zLine,"| %d: %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x", + &j, &x[0], &x[1], &x[2], &x[3], &x[4], &x[5], &x[6], &x[7], + &x[8], &x[9], &x[10], &x[11], &x[12], &x[13], &x[14], &x[15]); + if( rc==17 ){ + k = iOffset+j; + if( k+16<=n && k>=0 ){ + int ii; + for(ii=0; ii<16; ii++) a[k+ii] = x[ii]&0xff; + } + } + } + *pnData = n; + if( in!=p->in ){ + fclose(in); + }else{ + p->lineno = nLine; + } + return a; readHexDb_error: - if( in!=p->in ){ - fclose(in); - }else{ - while( fgets(zLine, sizeof(zLine), p->in)!=0 ){ - nLine++; - if(strncmp(zLine, "| end ", 6)==0 ) break; - } - p->lineno = nLine; + if( in!=p->in ){ + fclose(in); + }else{ + while( fgets(zLine, sizeof(zLine), p->in)!=0 ){ + nLine++; + if(strncmp(zLine, "| end ", 6)==0 ) break; } - sqlite3_free(a); - utf8_printf(stderr,"Error on line %d of --hexdb input\n", nLine); - return 0; + p->lineno = nLine; + } + sqlite3_free(a); + utf8_printf(stderr,"Error on line %d of --hexdb input\n", nLine); + return 0; } #endif /* SQLITE_OMIT_DESERIALIZE */ @@ -15561,27 +15561,27 @@ readHexDb_error: ** offset (4*) of the blob. */ static void shellInt32( - sqlite3_context *context, - int argc, - sqlite3_value **argv + sqlite3_context *context, + int argc, + sqlite3_value **argv ){ - const unsigned char *pBlob; - int nBlob; - int iInt; + const unsigned char *pBlob; + int nBlob; + int iInt; - UNUSED_PARAMETER(argc); - nBlob = sqlite3_value_bytes(argv[0]); - pBlob = (const unsigned char*)sqlite3_value_blob(argv[0]); - iInt = sqlite3_value_int(argv[1]); + UNUSED_PARAMETER(argc); + nBlob = sqlite3_value_bytes(argv[0]); + pBlob = (const unsigned char*)sqlite3_value_blob(argv[0]); + iInt = sqlite3_value_int(argv[1]); - if( iInt>=0 && (iInt+1)*4<=nBlob ){ - const unsigned char *a = &pBlob[iInt*4]; - sqlite3_int64 iVal = ((sqlite3_int64)a[0]<<24) - + ((sqlite3_int64)a[1]<<16) - + ((sqlite3_int64)a[2]<< 8) - + ((sqlite3_int64)a[3]<< 0); - sqlite3_result_int64(context, iVal); - } + if( iInt>=0 && (iInt+1)*4<=nBlob ){ + const unsigned char *a = &pBlob[iInt*4]; + sqlite3_int64 iVal = ((sqlite3_int64)a[0]<<24) + + ((sqlite3_int64)a[1]<<16) + + ((sqlite3_int64)a[2]<< 8) + + ((sqlite3_int64)a[3]<< 0); + sqlite3_result_int64(context, iVal); + } } /* @@ -15589,36 +15589,36 @@ static void shellInt32( ** using "..." with internal double-quote characters doubled. */ static void shellIdQuote( - sqlite3_context *context, - int argc, - sqlite3_value **argv + sqlite3_context *context, + int argc, + sqlite3_value **argv ){ - const char *zName = (const char*)sqlite3_value_text(argv[0]); - UNUSED_PARAMETER(argc); - if( zName ){ - char *z = sqlite3_mprintf("\"%w\"", zName); - sqlite3_result_text(context, z, -1, sqlite3_free); - } + const char *zName = (const char*)sqlite3_value_text(argv[0]); + UNUSED_PARAMETER(argc); + if( zName ){ + char *z = sqlite3_mprintf("\"%w\"", zName); + sqlite3_result_text(context, z, -1, sqlite3_free); + } } /* ** Scalar function "usleep(X)" invokes sqlite3_sleep(X) and returns X. */ static void shellUSleepFunc( - sqlite3_context *context, - int argcUnused, - sqlite3_value **argv + sqlite3_context *context, + int argcUnused, + sqlite3_value **argv ){ - int sleep = sqlite3_value_int(argv[0]); - (void)argcUnused; - sqlite3_sleep(sleep/1000); - sqlite3_result_int(context, sleep); + int sleep = sqlite3_value_int(argv[0]); + (void)argcUnused; + sqlite3_sleep(sleep/1000); + sqlite3_result_int(context, sleep); } /* ** Scalar function "shell_escape_crnl" used by the .recover command. ** The argument passed to this function is the output of built-in -** function quote(). If the first character of the input is "'", +** function quote(). If the first character of the input is "'", ** indicating that the value passed to quote() was a text value, ** then this function searches the input for "\n" and "\r" characters ** and adds a wrapper similar to the following: @@ -15629,81 +15629,81 @@ static void shellUSleepFunc( ** of the input is returned. */ static void shellEscapeCrnl( - sqlite3_context *context, - int argc, - sqlite3_value **argv + sqlite3_context *context, + int argc, + sqlite3_value **argv ){ - const char *zText = (const char*)sqlite3_value_text(argv[0]); - UNUSED_PARAMETER(argc); - if( zText[0]=='\'' ){ - int nText = sqlite3_value_bytes(argv[0]); - int i; - char zBuf1[20]; - char zBuf2[20]; - const char *zNL = 0; - const char *zCR = 0; - int nCR = 0; - int nNL = 0; - - for(i=0; zText[i]; i++){ - if( zNL==0 && zText[i]=='\n' ){ - zNL = unused_string(zText, "\\n", "\\012", zBuf1); - nNL = (int)strlen(zNL); - } - if( zCR==0 && zText[i]=='\r' ){ - zCR = unused_string(zText, "\\r", "\\015", zBuf2); - nCR = (int)strlen(zCR); - } + const char *zText = (const char*)sqlite3_value_text(argv[0]); + UNUSED_PARAMETER(argc); + if( zText[0]=='\'' ){ + int nText = sqlite3_value_bytes(argv[0]); + int i; + char zBuf1[20]; + char zBuf2[20]; + const char *zNL = 0; + const char *zCR = 0; + int nCR = 0; + int nNL = 0; + + for(i=0; zText[i]; i++){ + if( zNL==0 && zText[i]=='\n' ){ + zNL = unused_string(zText, "\\n", "\\012", zBuf1); + nNL = (int)strlen(zNL); + } + if( zCR==0 && zText[i]=='\r' ){ + zCR = unused_string(zText, "\\r", "\\015", zBuf2); + nCR = (int)strlen(zCR); + } + } + + if( zNL || zCR ){ + int iOut = 0; + i64 nMax = (nNL > nCR) ? nNL : nCR; + i64 nAlloc = nMax * nText + (nMax+64)*2; + char *zOut = (char*)sqlite3_malloc64(nAlloc); + if( zOut==0 ){ + sqlite3_result_error_nomem(context); + return; + } + + if( zNL && zCR ){ + memcpy(&zOut[iOut], "replace(replace(", 16); + iOut += 16; + }else{ + memcpy(&zOut[iOut], "replace(", 8); + iOut += 8; + } + for(i=0; zText[i]; i++){ + if( zText[i]=='\n' ){ + memcpy(&zOut[iOut], zNL, nNL); + iOut += nNL; + }else if( zText[i]=='\r' ){ + memcpy(&zOut[iOut], zCR, nCR); + iOut += nCR; + }else{ + zOut[iOut] = zText[i]; + iOut++; } + } - if( zNL || zCR ){ - int iOut = 0; - i64 nMax = (nNL > nCR) ? nNL : nCR; - i64 nAlloc = nMax * nText + (nMax+64)*2; - char *zOut = (char*)sqlite3_malloc64(nAlloc); - if( zOut==0 ){ - sqlite3_result_error_nomem(context); - return; - } - - if( zNL && zCR ){ - memcpy(&zOut[iOut], "replace(replace(", 16); - iOut += 16; - }else{ - memcpy(&zOut[iOut], "replace(", 8); - iOut += 8; - } - for(i=0; zText[i]; i++){ - if( zText[i]=='\n' ){ - memcpy(&zOut[iOut], zNL, nNL); - iOut += nNL; - }else if( zText[i]=='\r' ){ - memcpy(&zOut[iOut], zCR, nCR); - iOut += nCR; - }else{ - zOut[iOut] = zText[i]; - iOut++; - } - } - - if( zNL ){ - memcpy(&zOut[iOut], ",'", 2); iOut += 2; - memcpy(&zOut[iOut], zNL, nNL); iOut += nNL; - memcpy(&zOut[iOut], "', char(10))", 12); iOut += 12; - } - if( zCR ){ - memcpy(&zOut[iOut], ",'", 2); iOut += 2; - memcpy(&zOut[iOut], zCR, nCR); iOut += nCR; - memcpy(&zOut[iOut], "', char(13))", 12); iOut += 12; - } + if( zNL ){ + memcpy(&zOut[iOut], ",'", 2); iOut += 2; + memcpy(&zOut[iOut], zNL, nNL); iOut += nNL; + memcpy(&zOut[iOut], "', char(10))", 12); iOut += 12; + } + if( zCR ){ + memcpy(&zOut[iOut], ",'", 2); iOut += 2; + memcpy(&zOut[iOut], zCR, nCR); iOut += nCR; + memcpy(&zOut[iOut], "', char(13))", 12); iOut += 12; + } - sqlite3_result_text(context, zOut, iOut, SQLITE_TRANSIENT); - sqlite3_free(zOut); - return; - } + sqlite3_result_text(context, zOut, iOut, SQLITE_TRANSIENT); + sqlite3_free(zOut); + return; } + } - sqlite3_result_value(context, argv[0]); + sqlite3_result_value(context, argv[0]); } /* Flags for open_db(). @@ -15724,137 +15724,137 @@ static void shellEscapeCrnl( ** the database fails to open, print an error message and exit. */ static void open_db(ShellState *p, int openFlags){ - if( p->db==0 ){ - const char *zDbFilename = p->pAuxDb->zDbFilename; - if( p->openMode==SHELL_OPEN_UNSPEC ){ - if( zDbFilename==0 || zDbFilename[0]==0 ){ - p->openMode = SHELL_OPEN_NORMAL; - }else{ - p->openMode = (u8)deduceDatabaseType(zDbFilename, - (openFlags & OPEN_DB_ZIPFILE)!=0); - } - } - switch( p->openMode ){ - case SHELL_OPEN_APPENDVFS: { - sqlite3_open_v2(zDbFilename, &p->db, - SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|p->openFlags, "apndvfs"); - break; - } - case SHELL_OPEN_HEXDB: - case SHELL_OPEN_DESERIALIZE: { - sqlite3_open(0, &p->db); - break; - } - case SHELL_OPEN_ZIPFILE: { - sqlite3_open(":memory:", &p->db); - break; - } - case SHELL_OPEN_READONLY: { - sqlite3_open_v2(zDbFilename, &p->db, - SQLITE_OPEN_READONLY|p->openFlags, 0); - break; - } - case SHELL_OPEN_UNSPEC: - case SHELL_OPEN_NORMAL: { - sqlite3_open_v2(zDbFilename, &p->db, - SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|p->openFlags, 0); - break; - } - } - globalDb = p->db; - if( p->db==0 || SQLITE_OK!=sqlite3_errcode(p->db) ){ - utf8_printf(stderr,"Error: unable to open database \"%s\": %s\n", - zDbFilename, sqlite3_errmsg(p->db)); - if( openFlags & OPEN_DB_KEEPALIVE ){ - sqlite3_open(":memory:", &p->db); - return; - } - exit(1); - } + if( p->db==0 ){ + const char *zDbFilename = p->pAuxDb->zDbFilename; + if( p->openMode==SHELL_OPEN_UNSPEC ){ + if( zDbFilename==0 || zDbFilename[0]==0 ){ + p->openMode = SHELL_OPEN_NORMAL; + }else{ + p->openMode = (u8)deduceDatabaseType(zDbFilename, + (openFlags & OPEN_DB_ZIPFILE)!=0); + } + } + switch( p->openMode ){ + case SHELL_OPEN_APPENDVFS: { + sqlite3_open_v2(zDbFilename, &p->db, + SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|p->openFlags, "apndvfs"); + break; + } + case SHELL_OPEN_HEXDB: + case SHELL_OPEN_DESERIALIZE: { + sqlite3_open(0, &p->db); + break; + } + case SHELL_OPEN_ZIPFILE: { + sqlite3_open(":memory:", &p->db); + break; + } + case SHELL_OPEN_READONLY: { + sqlite3_open_v2(zDbFilename, &p->db, + SQLITE_OPEN_READONLY|p->openFlags, 0); + break; + } + case SHELL_OPEN_UNSPEC: + case SHELL_OPEN_NORMAL: { + sqlite3_open_v2(zDbFilename, &p->db, + SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|p->openFlags, 0); + break; + } + } + globalDb = p->db; + if( p->db==0 || SQLITE_OK!=sqlite3_errcode(p->db) ){ + utf8_printf(stderr,"Error: unable to open database \"%s\": %s\n", + zDbFilename, sqlite3_errmsg(p->db)); + if( openFlags & OPEN_DB_KEEPALIVE ){ + sqlite3_open(":memory:", &p->db); + return; + } + exit(1); + } #ifndef SQLITE_OMIT_LOAD_EXTENSION - sqlite3_enable_load_extension(p->db, 1); + sqlite3_enable_load_extension(p->db, 1); #endif - sqlite3_fileio_init(p->db, 0, 0); - sqlite3_shathree_init(p->db, 0, 0); - sqlite3_completion_init(p->db, 0, 0); - sqlite3_uint_init(p->db, 0, 0); - sqlite3_decimal_init(p->db, 0, 0); - sqlite3_regexp_init(p->db, 0, 0); - sqlite3_ieee_init(p->db, 0, 0); - sqlite3_series_init(p->db, 0, 0); + sqlite3_fileio_init(p->db, 0, 0); + sqlite3_shathree_init(p->db, 0, 0); + sqlite3_completion_init(p->db, 0, 0); + sqlite3_uint_init(p->db, 0, 0); + sqlite3_decimal_init(p->db, 0, 0); + sqlite3_regexp_init(p->db, 0, 0); + sqlite3_ieee_init(p->db, 0, 0); + sqlite3_series_init(p->db, 0, 0); #if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB) - sqlite3_dbdata_init(p->db, 0, 0); + sqlite3_dbdata_init(p->db, 0, 0); #endif #ifdef SQLITE_HAVE_ZLIB - sqlite3_zipfile_init(p->db, 0, 0); - sqlite3_sqlar_init(p->db, 0, 0); + sqlite3_zipfile_init(p->db, 0, 0); + sqlite3_sqlar_init(p->db, 0, 0); #endif - sqlite3_create_function(p->db, "shell_add_schema", 3, SQLITE_UTF8, 0, - shellAddSchemaName, 0, 0); - sqlite3_create_function(p->db, "shell_module_schema", 1, SQLITE_UTF8, 0, - shellModuleSchema, 0, 0); - sqlite3_create_function(p->db, "shell_putsnl", 1, SQLITE_UTF8, p, - shellPutsFunc, 0, 0); - sqlite3_create_function(p->db, "shell_escape_crnl", 1, SQLITE_UTF8, 0, - shellEscapeCrnl, 0, 0); - sqlite3_create_function(p->db, "shell_int32", 2, SQLITE_UTF8, 0, - shellInt32, 0, 0); - sqlite3_create_function(p->db, "shell_idquote", 1, SQLITE_UTF8, 0, - shellIdQuote, 0, 0); - sqlite3_create_function(p->db, "usleep",1,SQLITE_UTF8,0, - shellUSleepFunc, 0, 0); + sqlite3_create_function(p->db, "shell_add_schema", 3, SQLITE_UTF8, 0, + shellAddSchemaName, 0, 0); + sqlite3_create_function(p->db, "shell_module_schema", 1, SQLITE_UTF8, 0, + shellModuleSchema, 0, 0); + sqlite3_create_function(p->db, "shell_putsnl", 1, SQLITE_UTF8, p, + shellPutsFunc, 0, 0); + sqlite3_create_function(p->db, "shell_escape_crnl", 1, SQLITE_UTF8, 0, + shellEscapeCrnl, 0, 0); + sqlite3_create_function(p->db, "shell_int32", 2, SQLITE_UTF8, 0, + shellInt32, 0, 0); + sqlite3_create_function(p->db, "shell_idquote", 1, SQLITE_UTF8, 0, + shellIdQuote, 0, 0); + sqlite3_create_function(p->db, "usleep",1,SQLITE_UTF8,0, + shellUSleepFunc, 0, 0); #ifndef SQLITE_NOHAVE_SYSTEM - sqlite3_create_function(p->db, "edit", 1, SQLITE_UTF8, 0, - editFunc, 0, 0); - sqlite3_create_function(p->db, "edit", 2, SQLITE_UTF8, 0, - editFunc, 0, 0); -#endif - if( p->openMode==SHELL_OPEN_ZIPFILE ){ - char *zSql = sqlite3_mprintf( - "CREATE VIRTUAL TABLE zip USING zipfile(%Q);", zDbFilename); - sqlite3_exec(p->db, zSql, 0, 0, 0); - sqlite3_free(zSql); - } -#ifndef SQLITE_OMIT_DESERIALIZE - else - if( p->openMode==SHELL_OPEN_DESERIALIZE || p->openMode==SHELL_OPEN_HEXDB ){ - int rc; - int nData = 0; - unsigned char *aData; - if( p->openMode==SHELL_OPEN_DESERIALIZE ){ - aData = (unsigned char*)readFile(zDbFilename, &nData); - }else{ - aData = readHexDb(p, &nData); - if( aData==0 ){ - return; - } - } - rc = sqlite3_deserialize(p->db, "main", aData, nData, nData, - SQLITE_DESERIALIZE_RESIZEABLE | - SQLITE_DESERIALIZE_FREEONCLOSE); - if( rc ){ - utf8_printf(stderr, "Error: sqlite3_deserialize() returns %d\n", rc); - } - if( p->szMax>0 ){ - sqlite3_file_control(p->db, "main", SQLITE_FCNTL_SIZE_LIMIT, &p->szMax); - } - } + sqlite3_create_function(p->db, "edit", 1, SQLITE_UTF8, 0, + editFunc, 0, 0); + sqlite3_create_function(p->db, "edit", 2, SQLITE_UTF8, 0, + editFunc, 0, 0); #endif + if( p->openMode==SHELL_OPEN_ZIPFILE ){ + char *zSql = sqlite3_mprintf( + "CREATE VIRTUAL TABLE zip USING zipfile(%Q);", zDbFilename); + sqlite3_exec(p->db, zSql, 0, 0, 0); + sqlite3_free(zSql); } - if( p->bSafeModePersist && p->db!=0 ){ - sqlite3_set_authorizer(p->db, safeModeAuth, p); +#ifndef SQLITE_OMIT_DESERIALIZE + else + if( p->openMode==SHELL_OPEN_DESERIALIZE || p->openMode==SHELL_OPEN_HEXDB ){ + int rc; + int nData = 0; + unsigned char *aData; + if( p->openMode==SHELL_OPEN_DESERIALIZE ){ + aData = (unsigned char*)readFile(zDbFilename, &nData); + }else{ + aData = readHexDb(p, &nData); + if( aData==0 ){ + return; + } + } + rc = sqlite3_deserialize(p->db, "main", aData, nData, nData, + SQLITE_DESERIALIZE_RESIZEABLE | + SQLITE_DESERIALIZE_FREEONCLOSE); + if( rc ){ + utf8_printf(stderr, "Error: sqlite3_deserialize() returns %d\n", rc); + } + if( p->szMax>0 ){ + sqlite3_file_control(p->db, "main", SQLITE_FCNTL_SIZE_LIMIT, &p->szMax); + } } +#endif + } + if( p->bSafeModePersist && p->db!=0 ){ + sqlite3_set_authorizer(p->db, safeModeAuth, p); + } } /* ** Attempt to close the databaes connection. Report errors. */ void close_db(sqlite3 *db){ - int rc = sqlite3_close(db); - if( rc ){ - utf8_printf(stderr, "Error: sqlite3_close() returns %d: %s\n", - rc, sqlite3_errmsg(db)); - } + int rc = sqlite3_close(db); + if( rc ){ + utf8_printf(stderr, "Error: sqlite3_close() returns %d: %s\n", + rc, sqlite3_errmsg(db)); + } } #if HAVE_READLINE || HAVE_EDITLINE @@ -15862,28 +15862,28 @@ void close_db(sqlite3 *db){ ** Readline completion callbacks */ static char *readline_completion_generator(const char *text, int state){ - static sqlite3_stmt *pStmt = 0; - char *zRet; - if( state==0 ){ - char *zSql; - sqlite3_finalize(pStmt); - zSql = sqlite3_mprintf("SELECT DISTINCT candidate COLLATE nocase" - " FROM completion(%Q) ORDER BY 1", text); - sqlite3_prepare_v2(globalDb, zSql, -1, &pStmt, 0); - sqlite3_free(zSql); - } - if( sqlite3_step(pStmt)==SQLITE_ROW ){ - zRet = strdup((const char*)sqlite3_column_text(pStmt, 0)); - }else{ - sqlite3_finalize(pStmt); - pStmt = 0; - zRet = 0; - } - return zRet; + static sqlite3_stmt *pStmt = 0; + char *zRet; + if( state==0 ){ + char *zSql; + sqlite3_finalize(pStmt); + zSql = sqlite3_mprintf("SELECT DISTINCT candidate COLLATE nocase" + " FROM completion(%Q) ORDER BY 1", text); + sqlite3_prepare_v2(globalDb, zSql, -1, &pStmt, 0); + sqlite3_free(zSql); + } + if( sqlite3_step(pStmt)==SQLITE_ROW ){ + zRet = strdup((const char*)sqlite3_column_text(pStmt, 0)); + }else{ + sqlite3_finalize(pStmt); + pStmt = 0; + zRet = 0; + } + return zRet; } static char **readline_completion(const char *zText, int iStart, int iEnd){ - rl_attempted_completion_over = 1; - return rl_completion_matches(zText, readline_completion_generator); + rl_attempted_completion_over = 1; + return rl_completion_matches(zText, readline_completion_generator); } #elif HAVE_LINENOISE @@ -15891,33 +15891,33 @@ static char **readline_completion(const char *zText, int iStart, int iEnd){ ** Linenoise completion callback */ static void linenoise_completion(const char *zLine, linenoiseCompletions *lc){ - int nLine = strlen30(zLine); - int i, iStart; - sqlite3_stmt *pStmt = 0; - char *zSql; - char zBuf[1000]; - - if( nLine>sizeof(zBuf)-30 ) return; - if( zLine[0]=='.' || zLine[0]=='#') return; - for(i=nLine-1; i>=0 && (isalnum(zLine[i]) || zLine[i]=='_'); i--){} - if( i==nLine-1 ) return; - iStart = i+1; - memcpy(zBuf, zLine, iStart); - zSql = sqlite3_mprintf("SELECT DISTINCT candidate COLLATE nocase" - " FROM completion(%Q,%Q) ORDER BY 1", - &zLine[iStart], zLine); - sqlite3_prepare_v2(globalDb, zSql, -1, &pStmt, 0); - sqlite3_free(zSql); - sqlite3_exec(globalDb, "PRAGMA page_count", 0, 0, 0); /* Load the schema */ - while( sqlite3_step(pStmt)==SQLITE_ROW ){ - const char *zCompletion = (const char*)sqlite3_column_text(pStmt, 0); - int nCompletion = sqlite3_column_bytes(pStmt, 0); - if( iStart+nCompletion < sizeof(zBuf)-1 ){ - memcpy(zBuf+iStart, zCompletion, nCompletion+1); - linenoiseAddCompletion(lc, zBuf); - } - } - sqlite3_finalize(pStmt); + int nLine = strlen30(zLine); + int i, iStart; + sqlite3_stmt *pStmt = 0; + char *zSql; + char zBuf[1000]; + + if( nLine>sizeof(zBuf)-30 ) return; + if( zLine[0]=='.' || zLine[0]=='#') return; + for(i=nLine-1; i>=0 && (isalnum(zLine[i]) || zLine[i]=='_'); i--){} + if( i==nLine-1 ) return; + iStart = i+1; + memcpy(zBuf, zLine, iStart); + zSql = sqlite3_mprintf("SELECT DISTINCT candidate COLLATE nocase" + " FROM completion(%Q,%Q) ORDER BY 1", + &zLine[iStart], zLine); + sqlite3_prepare_v2(globalDb, zSql, -1, &pStmt, 0); + sqlite3_free(zSql); + sqlite3_exec(globalDb, "PRAGMA page_count", 0, 0, 0); /* Load the schema */ + while( sqlite3_step(pStmt)==SQLITE_ROW ){ + const char *zCompletion = (const char*)sqlite3_column_text(pStmt, 0); + int nCompletion = sqlite3_column_bytes(pStmt, 0); + if( iStart+nCompletion < sizeof(zBuf)-1 ){ + memcpy(zBuf+iStart, zCompletion, nCompletion+1); + linenoiseAddCompletion(lc, zBuf); + } + } + sqlite3_finalize(pStmt); } #endif @@ -15938,47 +15938,47 @@ static void linenoise_completion(const char *zLine, linenoiseCompletions *lc){ ** \NNN -> ascii character NNN in octal */ static void resolve_backslashes(char *z){ - int i, j; - char c; - while( *z && *z!='\\' ) z++; - for(i=j=0; (c = z[i])!=0; i++, j++){ - if( c=='\\' && z[i+1]!=0 ){ - c = z[++i]; - if( c=='a' ){ - c = '\a'; - }else if( c=='b' ){ - c = '\b'; - }else if( c=='t' ){ - c = '\t'; - }else if( c=='n' ){ - c = '\n'; - }else if( c=='v' ){ - c = '\v'; - }else if( c=='f' ){ - c = '\f'; - }else if( c=='r' ){ - c = '\r'; - }else if( c=='"' ){ - c = '"'; - }else if( c=='\'' ){ - c = '\''; - }else if( c=='\\' ){ - c = '\\'; - }else if( c>='0' && c<='7' ){ - c -= '0'; - if( z[i+1]>='0' && z[i+1]<='7' ){ - i++; - c = (c<<3) + z[i] - '0'; - if( z[i+1]>='0' && z[i+1]<='7' ){ - i++; - c = (c<<3) + z[i] - '0'; - } - } - } + int i, j; + char c; + while( *z && *z!='\\' ) z++; + for(i=j=0; (c = z[i])!=0; i++, j++){ + if( c=='\\' && z[i+1]!=0 ){ + c = z[++i]; + if( c=='a' ){ + c = '\a'; + }else if( c=='b' ){ + c = '\b'; + }else if( c=='t' ){ + c = '\t'; + }else if( c=='n' ){ + c = '\n'; + }else if( c=='v' ){ + c = '\v'; + }else if( c=='f' ){ + c = '\f'; + }else if( c=='r' ){ + c = '\r'; + }else if( c=='"' ){ + c = '"'; + }else if( c=='\'' ){ + c = '\''; + }else if( c=='\\' ){ + c = '\\'; + }else if( c>='0' && c<='7' ){ + c -= '0'; + if( z[i+1]>='0' && z[i+1]<='7' ){ + i++; + c = (c<<3) + z[i] - '0'; + if( z[i+1]>='0' && z[i+1]<='7' ){ + i++; + c = (c<<3) + z[i] - '0'; + } } - z[j] = c; + } } - if( j=0; i++){} - }else{ - for(i=0; zArg[i]>='0' && zArg[i]<='9'; i++){} - } - if( i>0 && zArg[i]==0 ) return (int)(integerValue(zArg) & 0xffffffff); - if( sqlite3_stricmp(zArg, "on")==0 || sqlite3_stricmp(zArg,"yes")==0 ){ - return 1; - } - if( sqlite3_stricmp(zArg, "off")==0 || sqlite3_stricmp(zArg,"no")==0 ){ - return 0; - } - utf8_printf(stderr, "ERROR: Not a boolean value: \"%s\". Assuming \"no\".\n", - zArg); + int i; + if( zArg[0]=='0' && zArg[1]=='x' ){ + for(i=2; hexDigitValue(zArg[i])>=0; i++){} + }else{ + for(i=0; zArg[i]>='0' && zArg[i]<='9'; i++){} + } + if( i>0 && zArg[i]==0 ) return (int)(integerValue(zArg) & 0xffffffff); + if( sqlite3_stricmp(zArg, "on")==0 || sqlite3_stricmp(zArg,"yes")==0 ){ + return 1; + } + if( sqlite3_stricmp(zArg, "off")==0 || sqlite3_stricmp(zArg,"no")==0 ){ return 0; + } + utf8_printf(stderr, "ERROR: Not a boolean value: \"%s\". Assuming \"no\".\n", + zArg); + return 0; } /* ** Set or clear a shell flag according to a boolean value. */ static void setOrClearFlag(ShellState *p, unsigned mFlag, const char *zArg){ - if( booleanValue(zArg) ){ - ShellSetFlag(p, mFlag); - }else{ - ShellClearFlag(p, mFlag); - } + if( booleanValue(zArg) ){ + ShellSetFlag(p, mFlag); + }else{ + ShellClearFlag(p, mFlag); + } } /* ** Close an output file, assuming it is not stderr or stdout */ static void output_file_close(FILE *f){ - if( f && f!=stdout && f!=stderr ) fclose(f); + if( f && f!=stdout && f!=stderr ) fclose(f); } /* @@ -16028,20 +16028,20 @@ static void output_file_close(FILE *f){ ** filename is "off". */ static FILE *output_file_open(const char *zFile, int bTextMode){ - FILE *f; - if( strcmp(zFile,"stdout")==0 ){ - f = stdout; - }else if( strcmp(zFile, "stderr")==0 ){ - f = stderr; - }else if( strcmp(zFile, "off")==0 ){ - f = 0; - }else{ - f = fopen(zFile, bTextMode ? "w" : "wb"); - if( f==0 ){ - utf8_printf(stderr, "Error: cannot open \"%s\"\n", zFile); - } + FILE *f; + if( strcmp(zFile,"stdout")==0 ){ + f = stdout; + }else if( strcmp(zFile, "stderr")==0 ){ + f = stderr; + }else if( strcmp(zFile, "off")==0 ){ + f = 0; + }else{ + f = fopen(zFile, bTextMode ? "w" : "wb"); + if( f==0 ){ + utf8_printf(stderr, "Error: cannot open \"%s\"\n", zFile); } - return f; + } + return f; } #ifndef SQLITE_OMIT_TRACE @@ -16049,57 +16049,57 @@ static FILE *output_file_open(const char *zFile, int bTextMode){ ** A routine for handling output from sqlite3_trace(). */ static int sql_trace_callback( - unsigned mType, /* The trace type */ - void *pArg, /* The ShellState pointer */ - void *pP, /* Usually a pointer to sqlite_stmt */ - void *pX /* Auxiliary output */ + unsigned mType, /* The trace type */ + void *pArg, /* The ShellState pointer */ + void *pP, /* Usually a pointer to sqlite_stmt */ + void *pX /* Auxiliary output */ ){ - ShellState *p = (ShellState*)pArg; - sqlite3_stmt *pStmt; - const char *zSql; - int nSql; - if( p->traceOut==0 ) return 0; - if( mType==SQLITE_TRACE_CLOSE ){ - utf8_printf(p->traceOut, "-- closing database connection\n"); - return 0; - } - if( mType!=SQLITE_TRACE_ROW && ((const char*)pX)[0]=='-' ){ - zSql = (const char*)pX; - }else{ - pStmt = (sqlite3_stmt*)pP; - switch( p->eTraceType ){ - case SHELL_TRACE_EXPANDED: { - zSql = sqlite3_expanded_sql(pStmt); - break; - } + ShellState *p = (ShellState*)pArg; + sqlite3_stmt *pStmt; + const char *zSql; + int nSql; + if( p->traceOut==0 ) return 0; + if( mType==SQLITE_TRACE_CLOSE ){ + utf8_printf(p->traceOut, "-- closing database connection\n"); + return 0; + } + if( mType!=SQLITE_TRACE_ROW && ((const char*)pX)[0]=='-' ){ + zSql = (const char*)pX; + }else{ + pStmt = (sqlite3_stmt*)pP; + switch( p->eTraceType ){ + case SHELL_TRACE_EXPANDED: { + zSql = sqlite3_expanded_sql(pStmt); + break; + } #ifdef SQLITE_ENABLE_NORMALIZE - case SHELL_TRACE_NORMALIZED: { - zSql = sqlite3_normalized_sql(pStmt); - break; - } + case SHELL_TRACE_NORMALIZED: { + zSql = sqlite3_normalized_sql(pStmt); + break; + } #endif - default: { - zSql = sqlite3_sql(pStmt); - break; - } - } - } - if( zSql==0 ) return 0; - nSql = strlen30(zSql); - while( nSql>0 && zSql[nSql-1]==';' ){ nSql--; } - switch( mType ){ - case SQLITE_TRACE_ROW: - case SQLITE_TRACE_STMT: { - utf8_printf(p->traceOut, "%.*s;\n", nSql, zSql); - break; - } - case SQLITE_TRACE_PROFILE: { - sqlite3_int64 nNanosec = *(sqlite3_int64*)pX; - utf8_printf(p->traceOut, "%.*s; -- %lld ns\n", nSql, zSql, nNanosec); - break; - } - } - return 0; + default: { + zSql = sqlite3_sql(pStmt); + break; + } + } + } + if( zSql==0 ) return 0; + nSql = strlen30(zSql); + while( nSql>0 && zSql[nSql-1]==';' ){ nSql--; } + switch( mType ){ + case SQLITE_TRACE_ROW: + case SQLITE_TRACE_STMT: { + utf8_printf(p->traceOut, "%.*s;\n", nSql, zSql); + break; + } + case SQLITE_TRACE_PROFILE: { + sqlite3_int64 nNanosec = *(sqlite3_int64*)pX; + utf8_printf(p->traceOut, "%.*s; -- %lld ns\n", nSql, zSql, nNanosec); + break; + } + } + return 0; } #endif @@ -16108,8 +16108,8 @@ static int sql_trace_callback( ** a useful spot to set a debugger breakpoint. */ static void test_breakpoint(void){ - static int nCall = 0; - nCall++; + static int nCall = 0; + nCall++; } /* @@ -16117,39 +16117,39 @@ static void test_breakpoint(void){ */ typedef struct ImportCtx ImportCtx; struct ImportCtx { - const char *zFile; /* Name of the input file */ - FILE *in; /* Read the CSV text from this input stream */ - int (SQLITE_CDECL *xCloser)(FILE*); /* Func to close in */ - char *z; /* Accumulated text for a field */ - int n; /* Number of bytes in z */ - int nAlloc; /* Space allocated for z[] */ - int nLine; /* Current line number */ - int nRow; /* Number of rows imported */ - int nErr; /* Number of errors encountered */ - int bNotFirst; /* True if one or more bytes already read */ - int cTerm; /* Character that terminated the most recent field */ - int cColSep; /* The column separator character. (Usually ",") */ - int cRowSep; /* The row separator character. (Usually "\n") */ + const char *zFile; /* Name of the input file */ + FILE *in; /* Read the CSV text from this input stream */ + int (SQLITE_CDECL *xCloser)(FILE*); /* Func to close in */ + char *z; /* Accumulated text for a field */ + int n; /* Number of bytes in z */ + int nAlloc; /* Space allocated for z[] */ + int nLine; /* Current line number */ + int nRow; /* Number of rows imported */ + int nErr; /* Number of errors encountered */ + int bNotFirst; /* True if one or more bytes already read */ + int cTerm; /* Character that terminated the most recent field */ + int cColSep; /* The column separator character. (Usually ",") */ + int cRowSep; /* The row separator character. (Usually "\n") */ }; /* Clean up resourced used by an ImportCtx */ static void import_cleanup(ImportCtx *p){ - if( p->in!=0 && p->xCloser!=0 ){ - p->xCloser(p->in); - p->in = 0; - } - sqlite3_free(p->z); - p->z = 0; + if( p->in!=0 && p->xCloser!=0 ){ + p->xCloser(p->in); + p->in = 0; + } + sqlite3_free(p->z); + p->z = 0; } /* Append a single byte to z[] */ static void import_append_char(ImportCtx *p, int c){ - if( p->n+1>=p->nAlloc ){ - p->nAlloc += p->nAlloc + 100; - p->z = sqlite3_realloc64(p->z, p->nAlloc); - if( p->z==0 ) shell_out_of_memory(); - } - p->z[p->n++] = (char)c; + if( p->n+1>=p->nAlloc ){ + p->nAlloc += p->nAlloc + 100; + p->z = sqlite3_realloc64(p->z, p->nAlloc); + if( p->z==0 ) shell_out_of_memory(); + } + p->z[p->n++] = (char)c; } /* Read a single field of CSV text. Compatible with rfc4180 and extended @@ -16166,81 +16166,81 @@ static void import_append_char(ImportCtx *p, int c){ ** + Report syntax errors on stderr */ static char *SQLITE_CDECL csv_read_one_field(ImportCtx *p){ - int c; - int cSep = p->cColSep; - int rSep = p->cRowSep; - p->n = 0; - c = fgetc(p->in); - if( c==EOF || seenInterrupt ){ - p->cTerm = EOF; - return 0; - } - if( c=='"' ){ - int pc, ppc; - int startLine = p->nLine; - int cQuote = c; - pc = ppc = 0; - while( 1 ){ - c = fgetc(p->in); - if( c==rSep ) p->nLine++; - if( c==cQuote ){ - if( pc==cQuote ){ - pc = 0; - continue; - } - } - if( (c==cSep && pc==cQuote) - || (c==rSep && pc==cQuote) - || (c==rSep && pc=='\r' && ppc==cQuote) - || (c==EOF && pc==cQuote) - ){ - do{ p->n--; }while( p->z[p->n]!=cQuote ); - p->cTerm = c; - break; - } - if( pc==cQuote && c!='\r' ){ - utf8_printf(stderr, "%s:%d: unescaped %c character\n", - p->zFile, p->nLine, cQuote); - } - if( c==EOF ){ - utf8_printf(stderr, "%s:%d: unterminated %c-quoted field\n", - p->zFile, startLine, cQuote); - p->cTerm = c; - break; - } - import_append_char(p, c); - ppc = pc; - pc = c; - } - }else{ - /* If this is the first field being parsed and it begins with the + int c; + int cSep = p->cColSep; + int rSep = p->cRowSep; + p->n = 0; + c = fgetc(p->in); + if( c==EOF || seenInterrupt ){ + p->cTerm = EOF; + return 0; + } + if( c=='"' ){ + int pc, ppc; + int startLine = p->nLine; + int cQuote = c; + pc = ppc = 0; + while( 1 ){ + c = fgetc(p->in); + if( c==rSep ) p->nLine++; + if( c==cQuote ){ + if( pc==cQuote ){ + pc = 0; + continue; + } + } + if( (c==cSep && pc==cQuote) + || (c==rSep && pc==cQuote) + || (c==rSep && pc=='\r' && ppc==cQuote) + || (c==EOF && pc==cQuote) + ){ + do{ p->n--; }while( p->z[p->n]!=cQuote ); + p->cTerm = c; + break; + } + if( pc==cQuote && c!='\r' ){ + utf8_printf(stderr, "%s:%d: unescaped %c character\n", + p->zFile, p->nLine, cQuote); + } + if( c==EOF ){ + utf8_printf(stderr, "%s:%d: unterminated %c-quoted field\n", + p->zFile, startLine, cQuote); + p->cTerm = c; + break; + } + import_append_char(p, c); + ppc = pc; + pc = c; + } + }else{ + /* If this is the first field being parsed and it begins with the ** UTF-8 BOM (0xEF BB BF) then skip the BOM */ - if( (c&0xff)==0xef && p->bNotFirst==0 ){ - import_append_char(p, c); - c = fgetc(p->in); - if( (c&0xff)==0xbb ){ - import_append_char(p, c); - c = fgetc(p->in); - if( (c&0xff)==0xbf ){ - p->bNotFirst = 1; - p->n = 0; - return csv_read_one_field(p); - } - } - } - while( c!=EOF && c!=cSep && c!=rSep ){ - import_append_char(p, c); - c = fgetc(p->in); - } - if( c==rSep ){ - p->nLine++; - if( p->n>0 && p->z[p->n-1]=='\r' ) p->n--; + if( (c&0xff)==0xef && p->bNotFirst==0 ){ + import_append_char(p, c); + c = fgetc(p->in); + if( (c&0xff)==0xbb ){ + import_append_char(p, c); + c = fgetc(p->in); + if( (c&0xff)==0xbf ){ + p->bNotFirst = 1; + p->n = 0; + return csv_read_one_field(p); } - p->cTerm = c; + } + } + while( c!=EOF && c!=cSep && c!=rSep ){ + import_append_char(p, c); + c = fgetc(p->in); + } + if( c==rSep ){ + p->nLine++; + if( p->n>0 && p->z[p->n-1]=='\r' ) p->n--; } - if( p->z ) p->z[p->n] = 0; - p->bNotFirst = 1; - return p->z; + p->cTerm = c; + } + if( p->z ) p->z[p->n] = 0; + p->bNotFirst = 1; + return p->z; } /* Read a single field of ASCII delimited text. @@ -16256,25 +16256,25 @@ static char *SQLITE_CDECL csv_read_one_field(ImportCtx *p){ ** + Report syntax errors on stderr */ static char *SQLITE_CDECL ascii_read_one_field(ImportCtx *p){ - int c; - int cSep = p->cColSep; - int rSep = p->cRowSep; - p->n = 0; + int c; + int cSep = p->cColSep; + int rSep = p->cRowSep; + p->n = 0; + c = fgetc(p->in); + if( c==EOF || seenInterrupt ){ + p->cTerm = EOF; + return 0; + } + while( c!=EOF && c!=cSep && c!=rSep ){ + import_append_char(p, c); c = fgetc(p->in); - if( c==EOF || seenInterrupt ){ - p->cTerm = EOF; - return 0; - } - while( c!=EOF && c!=cSep && c!=rSep ){ - import_append_char(p, c); - c = fgetc(p->in); - } - if( c==rSep ){ - p->nLine++; - } - p->cTerm = c; - if( p->z ) p->z[p->n] = 0; - return p->z; + } + if( c==rSep ){ + p->nLine++; + } + p->cTerm = c; + if( p->z ) p->z[p->n] = 0; + return p->z; } /* @@ -16283,106 +16283,106 @@ static char *SQLITE_CDECL ascii_read_one_field(ImportCtx *p){ ** work for WITHOUT ROWID tables. */ static void tryToCloneData( - ShellState *p, - sqlite3 *newDb, - const char *zTable + ShellState *p, + sqlite3 *newDb, + const char *zTable ){ - sqlite3_stmt *pQuery = 0; - sqlite3_stmt *pInsert = 0; - char *zQuery = 0; - char *zInsert = 0; - int rc; - int i, j, n; - int nTable = strlen30(zTable); - int k = 0; - int cnt = 0; - const int spinRate = 10000; - - zQuery = sqlite3_mprintf("SELECT * FROM \"%w\"", zTable); - rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0); - if( rc ){ - utf8_printf(stderr, "Error %d: %s on [%s]\n", + sqlite3_stmt *pQuery = 0; + sqlite3_stmt *pInsert = 0; + char *zQuery = 0; + char *zInsert = 0; + int rc; + int i, j, n; + int nTable = strlen30(zTable); + int k = 0; + int cnt = 0; + const int spinRate = 10000; + + zQuery = sqlite3_mprintf("SELECT * FROM \"%w\"", zTable); + rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0); + if( rc ){ + utf8_printf(stderr, "Error %d: %s on [%s]\n", sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db), zQuery); - goto end_data_xfer; - } - n = sqlite3_column_count(pQuery); - zInsert = sqlite3_malloc64(200 + nTable + n*3); - if( zInsert==0 ) shell_out_of_memory(); - sqlite3_snprintf(200+nTable,zInsert, - "INSERT OR IGNORE INTO \"%s\" VALUES(?", zTable); - i = strlen30(zInsert); - for(j=1; jdb, zQuery, -1, &pQuery, 0); - if( rc ){ - utf8_printf(stderr, "Warning: cannot step \"%s\" backwards", zTable); + goto end_data_xfer; + } + for(k=0; k<2; k++){ + while( (rc = sqlite3_step(pQuery))==SQLITE_ROW ){ + for(i=0; idb, zQuery, -1, &pQuery, 0); + if( rc ){ + utf8_printf(stderr, "Warning: cannot step \"%s\" backwards", zTable); + break; + } + } /* End for(k=0...) */ + +end_data_xfer: + sqlite3_finalize(pQuery); + sqlite3_finalize(pInsert); + sqlite3_free(zQuery); + sqlite3_free(zInsert); } @@ -16393,73 +16393,73 @@ end_data_xfer: ** sqlite_schema table, try again moving backwards. */ static void tryToCloneSchema( - ShellState *p, - sqlite3 *newDb, - const char *zWhere, - void (*xForEach)(ShellState*,sqlite3*,const char*) + ShellState *p, + sqlite3 *newDb, + const char *zWhere, + void (*xForEach)(ShellState*,sqlite3*,const char*) ){ - sqlite3_stmt *pQuery = 0; - char *zQuery = 0; - int rc; - const unsigned char *zName; - const unsigned char *zSql; - char *zErrMsg = 0; - - zQuery = sqlite3_mprintf("SELECT name, sql FROM sqlite_schema" - " WHERE %s", zWhere); - rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0); - if( rc ){ - utf8_printf(stderr, "Error: (%d) %s on [%s]\n", - sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db), - zQuery); - goto end_schema_xfer; + sqlite3_stmt *pQuery = 0; + char *zQuery = 0; + int rc; + const unsigned char *zName; + const unsigned char *zSql; + char *zErrMsg = 0; + + zQuery = sqlite3_mprintf("SELECT name, sql FROM sqlite_schema" + " WHERE %s", zWhere); + rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0); + if( rc ){ + utf8_printf(stderr, "Error: (%d) %s on [%s]\n", + sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db), + zQuery); + goto end_schema_xfer; + } + while( (rc = sqlite3_step(pQuery))==SQLITE_ROW ){ + zName = sqlite3_column_text(pQuery, 0); + zSql = sqlite3_column_text(pQuery, 1); + printf("%s... ", zName); fflush(stdout); + sqlite3_exec(newDb, (const char*)zSql, 0, 0, &zErrMsg); + if( zErrMsg ){ + utf8_printf(stderr, "Error: %s\nSQL: [%s]\n", zErrMsg, zSql); + sqlite3_free(zErrMsg); + zErrMsg = 0; } - while( (rc = sqlite3_step(pQuery))==SQLITE_ROW ){ - zName = sqlite3_column_text(pQuery, 0); - zSql = sqlite3_column_text(pQuery, 1); - printf("%s... ", zName); fflush(stdout); - sqlite3_exec(newDb, (const char*)zSql, 0, 0, &zErrMsg); - if( zErrMsg ){ - utf8_printf(stderr, "Error: %s\nSQL: [%s]\n", zErrMsg, zSql); - sqlite3_free(zErrMsg); - zErrMsg = 0; - } - if( xForEach ){ - xForEach(p, newDb, (const char*)zName); - } - printf("done\n"); - } - if( rc!=SQLITE_DONE ){ - sqlite3_finalize(pQuery); - sqlite3_free(zQuery); - zQuery = sqlite3_mprintf("SELECT name, sql FROM sqlite_schema" - " WHERE %s ORDER BY rowid DESC", zWhere); - rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0); - if( rc ){ - utf8_printf(stderr, "Error: (%d) %s on [%s]\n", - sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db), - zQuery); - goto end_schema_xfer; - } - while( sqlite3_step(pQuery)==SQLITE_ROW ){ - zName = sqlite3_column_text(pQuery, 0); - zSql = sqlite3_column_text(pQuery, 1); - printf("%s... ", zName); fflush(stdout); - sqlite3_exec(newDb, (const char*)zSql, 0, 0, &zErrMsg); - if( zErrMsg ){ - utf8_printf(stderr, "Error: %s\nSQL: [%s]\n", zErrMsg, zSql); - sqlite3_free(zErrMsg); - zErrMsg = 0; - } - if( xForEach ){ - xForEach(p, newDb, (const char*)zName); - } - printf("done\n"); - } + if( xForEach ){ + xForEach(p, newDb, (const char*)zName); } -end_schema_xfer: + printf("done\n"); + } + if( rc!=SQLITE_DONE ){ sqlite3_finalize(pQuery); sqlite3_free(zQuery); + zQuery = sqlite3_mprintf("SELECT name, sql FROM sqlite_schema" + " WHERE %s ORDER BY rowid DESC", zWhere); + rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0); + if( rc ){ + utf8_printf(stderr, "Error: (%d) %s on [%s]\n", + sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db), + zQuery); + goto end_schema_xfer; + } + while( sqlite3_step(pQuery)==SQLITE_ROW ){ + zName = sqlite3_column_text(pQuery, 0); + zSql = sqlite3_column_text(pQuery, 1); + printf("%s... ", zName); fflush(stdout); + sqlite3_exec(newDb, (const char*)zSql, 0, 0, &zErrMsg); + if( zErrMsg ){ + utf8_printf(stderr, "Error: %s\nSQL: [%s]\n", zErrMsg, zSql); + sqlite3_free(zErrMsg); + zErrMsg = 0; + } + if( xForEach ){ + xForEach(p, newDb, (const char*)zName); + } + printf("done\n"); + } + } +end_schema_xfer: + sqlite3_finalize(pQuery); + sqlite3_free(zQuery); } /* @@ -16468,25 +16468,25 @@ end_schema_xfer: ** into zNewDb. */ static void tryToClone(ShellState *p, const char *zNewDb){ - int rc; - sqlite3 *newDb = 0; - if( access(zNewDb,0)==0 ){ - utf8_printf(stderr, "File \"%s\" already exists.\n", zNewDb); - return; - } - rc = sqlite3_open(zNewDb, &newDb); - if( rc ){ - utf8_printf(stderr, "Cannot create output database: %s\n", + int rc; + sqlite3 *newDb = 0; + if( access(zNewDb,0)==0 ){ + utf8_printf(stderr, "File \"%s\" already exists.\n", zNewDb); + return; + } + rc = sqlite3_open(zNewDb, &newDb); + if( rc ){ + utf8_printf(stderr, "Cannot create output database: %s\n", sqlite3_errmsg(newDb)); - }else{ - sqlite3_exec(p->db, "PRAGMA writable_schema=ON;", 0, 0, 0); - sqlite3_exec(newDb, "BEGIN EXCLUSIVE;", 0, 0, 0); - tryToCloneSchema(p, newDb, "type='table'", tryToCloneData); - tryToCloneSchema(p, newDb, "type!='table'", 0); - sqlite3_exec(newDb, "COMMIT;", 0, 0, 0); - sqlite3_exec(p->db, "PRAGMA writable_schema=OFF;", 0, 0, 0); - } - close_db(newDb); + }else{ + sqlite3_exec(p->db, "PRAGMA writable_schema=ON;", 0, 0, 0); + sqlite3_exec(newDb, "BEGIN EXCLUSIVE;", 0, 0, 0); + tryToCloneSchema(p, newDb, "type='table'", tryToCloneData); + tryToCloneSchema(p, newDb, "type!='table'", 0); + sqlite3_exec(newDb, "COMMIT;", 0, 0, 0); + sqlite3_exec(p->db, "PRAGMA writable_schema=OFF;", 0, 0, 0); + } + close_db(newDb); } /* @@ -16497,64 +16497,64 @@ static void tryToClone(ShellState *p, const char *zNewDb){ ** launch start/open/xdg-open on that temporary file. */ static void output_reset(ShellState *p){ - if( p->outfile[0]=='|' ){ + if( p->outfile[0]=='|' ){ #ifndef SQLITE_OMIT_POPEN - pclose(p->out); + pclose(p->out); #endif - }else{ - output_file_close(p->out); + }else{ + output_file_close(p->out); #ifndef SQLITE_NOHAVE_SYSTEM - if( p->doXdgOpen ){ - const char *zXdgOpenCmd = + if( p->doXdgOpen ){ + const char *zXdgOpenCmd = #if defined(_WIN32) - "start"; + "start"; #elif defined(__APPLE__) - "open"; + "open"; #else - "xdg-open"; + "xdg-open"; #endif - char *zCmd; - zCmd = sqlite3_mprintf("%s %s", zXdgOpenCmd, p->zTempFile); - if( system(zCmd) ){ - utf8_printf(stderr, "Failed: [%s]\n", zCmd); - }else{ - /* Give the start/open/xdg-open command some time to get + char *zCmd; + zCmd = sqlite3_mprintf("%s %s", zXdgOpenCmd, p->zTempFile); + if( system(zCmd) ){ + utf8_printf(stderr, "Failed: [%s]\n", zCmd); + }else{ + /* Give the start/open/xdg-open command some time to get ** going before we continue, and potential delete the ** p->zTempFile data file out from under it */ - sqlite3_sleep(2000); - } - sqlite3_free(zCmd); - outputModePop(p); - p->doXdgOpen = 0; - } -#endif /* !defined(SQLITE_NOHAVE_SYSTEM) */ + sqlite3_sleep(2000); + } + sqlite3_free(zCmd); + outputModePop(p); + p->doXdgOpen = 0; } - p->outfile[0] = 0; - p->out = stdout; +#endif /* !defined(SQLITE_NOHAVE_SYSTEM) */ + } + p->outfile[0] = 0; + p->out = stdout; } /* ** Run an SQL command and return the single integer result. */ static int db_int(ShellState *p, const char *zSql){ - sqlite3_stmt *pStmt; - int res = 0; - sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); - if( pStmt && sqlite3_step(pStmt)==SQLITE_ROW ){ - res = sqlite3_column_int(pStmt,0); - } - sqlite3_finalize(pStmt); - return res; + sqlite3_stmt *pStmt; + int res = 0; + sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); + if( pStmt && sqlite3_step(pStmt)==SQLITE_ROW ){ + res = sqlite3_column_int(pStmt,0); + } + sqlite3_finalize(pStmt); + return res; } /* ** Convert a 2-byte or 4-byte big-endian integer into a native integer */ static unsigned int get2byteInt(unsigned char *a){ - return (a[0]<<8) + a[1]; + return (a[0]<<8) + a[1]; } static unsigned int get4byteInt(unsigned char *a){ - return (a[0]<<24) + (a[1]<<16) + (a[2]<<8) + a[3]; + return (a[0]<<24) + (a[1]<<16) + (a[2]<<8) + a[3]; } /* @@ -16563,104 +16563,104 @@ static unsigned int get4byteInt(unsigned char *a){ ** Return 1 on error, 2 to exit, and 0 otherwise. */ static int shell_dbinfo_command(ShellState *p, int nArg, char **azArg){ - static const struct { const char *zName; int ofst; } aField[] = { - { "file change counter:", 24 }, - { "database page count:", 28 }, - { "freelist page count:", 36 }, - { "schema cookie:", 40 }, - { "schema format:", 44 }, - { "default cache size:", 48 }, - { "autovacuum top root:", 52 }, - { "incremental vacuum:", 64 }, - { "text encoding:", 56 }, - { "user version:", 60 }, - { "application id:", 68 }, - { "software version:", 96 }, - }; - static const struct { const char *zName; const char *zSql; } aQuery[] = { - { "number of tables:", - "SELECT count(*) FROM %s WHERE type='table'" }, - { "number of indexes:", - "SELECT count(*) FROM %s WHERE type='index'" }, - { "number of triggers:", - "SELECT count(*) FROM %s WHERE type='trigger'" }, - { "number of views:", - "SELECT count(*) FROM %s WHERE type='view'" }, - { "schema size:", - "SELECT total(length(sql)) FROM %s" }, - }; - int i, rc; - unsigned iDataVersion; - char *zSchemaTab; - char *zDb = nArg>=2 ? azArg[1] : "main"; - sqlite3_stmt *pStmt = 0; - unsigned char aHdr[100]; - open_db(p, 0); - if( p->db==0 ) return 1; - rc = sqlite3_prepare_v2(p->db, - "SELECT data FROM sqlite_dbpage(?1) WHERE pgno=1", - -1, &pStmt, 0); - if( rc ){ - utf8_printf(stderr, "error: %s\n", sqlite3_errmsg(p->db)); - sqlite3_finalize(pStmt); - return 1; - } - sqlite3_bind_text(pStmt, 1, zDb, -1, SQLITE_STATIC); - if( sqlite3_step(pStmt)==SQLITE_ROW - && sqlite3_column_bytes(pStmt,0)>100 - ){ - memcpy(aHdr, sqlite3_column_blob(pStmt,0), 100); - sqlite3_finalize(pStmt); - }else{ - raw_printf(stderr, "unable to read database header\n"); - sqlite3_finalize(pStmt); - return 1; - } - i = get2byteInt(aHdr+16); - if( i==1 ) i = 65536; - utf8_printf(p->out, "%-20s %d\n", "database page size:", i); - utf8_printf(p->out, "%-20s %d\n", "write format:", aHdr[18]); - utf8_printf(p->out, "%-20s %d\n", "read format:", aHdr[19]); - utf8_printf(p->out, "%-20s %d\n", "reserved bytes:", aHdr[20]); - for(i=0; iout, "%-20s %u", aField[i].zName, val); - switch( ofst ){ - case 56: { - if( val==1 ) raw_printf(p->out, " (utf8)"); - if( val==2 ) raw_printf(p->out, " (utf16le)"); - if( val==3 ) raw_printf(p->out, " (utf16be)"); - } - } - raw_printf(p->out, "\n"); - } - if( zDb==0 ){ - zSchemaTab = sqlite3_mprintf("main.sqlite_schema"); - }else if( strcmp(zDb,"temp")==0 ){ - zSchemaTab = sqlite3_mprintf("%s", "sqlite_temp_schema"); - }else{ - zSchemaTab = sqlite3_mprintf("\"%w\".sqlite_schema", zDb); - } - for(i=0; iout, "%-20s %d\n", aQuery[i].zName, val); + static const struct { const char *zName; int ofst; } aField[] = { + { "file change counter:", 24 }, + { "database page count:", 28 }, + { "freelist page count:", 36 }, + { "schema cookie:", 40 }, + { "schema format:", 44 }, + { "default cache size:", 48 }, + { "autovacuum top root:", 52 }, + { "incremental vacuum:", 64 }, + { "text encoding:", 56 }, + { "user version:", 60 }, + { "application id:", 68 }, + { "software version:", 96 }, + }; + static const struct { const char *zName; const char *zSql; } aQuery[] = { + { "number of tables:", + "SELECT count(*) FROM %s WHERE type='table'" }, + { "number of indexes:", + "SELECT count(*) FROM %s WHERE type='index'" }, + { "number of triggers:", + "SELECT count(*) FROM %s WHERE type='trigger'" }, + { "number of views:", + "SELECT count(*) FROM %s WHERE type='view'" }, + { "schema size:", + "SELECT total(length(sql)) FROM %s" }, + }; + int i, rc; + unsigned iDataVersion; + char *zSchemaTab; + char *zDb = nArg>=2 ? azArg[1] : "main"; + sqlite3_stmt *pStmt = 0; + unsigned char aHdr[100]; + open_db(p, 0); + if( p->db==0 ) return 1; + rc = sqlite3_prepare_v2(p->db, + "SELECT data FROM sqlite_dbpage(?1) WHERE pgno=1", + -1, &pStmt, 0); + if( rc ){ + utf8_printf(stderr, "error: %s\n", sqlite3_errmsg(p->db)); + sqlite3_finalize(pStmt); + return 1; + } + sqlite3_bind_text(pStmt, 1, zDb, -1, SQLITE_STATIC); + if( sqlite3_step(pStmt)==SQLITE_ROW + && sqlite3_column_bytes(pStmt,0)>100 + ){ + memcpy(aHdr, sqlite3_column_blob(pStmt,0), 100); + sqlite3_finalize(pStmt); + }else{ + raw_printf(stderr, "unable to read database header\n"); + sqlite3_finalize(pStmt); + return 1; + } + i = get2byteInt(aHdr+16); + if( i==1 ) i = 65536; + utf8_printf(p->out, "%-20s %d\n", "database page size:", i); + utf8_printf(p->out, "%-20s %d\n", "write format:", aHdr[18]); + utf8_printf(p->out, "%-20s %d\n", "read format:", aHdr[19]); + utf8_printf(p->out, "%-20s %d\n", "reserved bytes:", aHdr[20]); + for(i=0; iout, "%-20s %u", aField[i].zName, val); + switch( ofst ){ + case 56: { + if( val==1 ) raw_printf(p->out, " (utf8)"); + if( val==2 ) raw_printf(p->out, " (utf16le)"); + if( val==3 ) raw_printf(p->out, " (utf16be)"); + } } - sqlite3_free(zSchemaTab); - sqlite3_file_control(p->db, zDb, SQLITE_FCNTL_DATA_VERSION, &iDataVersion); - utf8_printf(p->out, "%-20s %u\n", "data version", iDataVersion); - return 0; + raw_printf(p->out, "\n"); + } + if( zDb==0 ){ + zSchemaTab = sqlite3_mprintf("main.sqlite_schema"); + }else if( strcmp(zDb,"temp")==0 ){ + zSchemaTab = sqlite3_mprintf("%s", "sqlite_temp_schema"); + }else{ + zSchemaTab = sqlite3_mprintf("\"%w\".sqlite_schema", zDb); + } + for(i=0; iout, "%-20s %d\n", aQuery[i].zName, val); + } + sqlite3_free(zSchemaTab); + sqlite3_file_control(p->db, zDb, SQLITE_FCNTL_DATA_VERSION, &iDataVersion); + utf8_printf(p->out, "%-20s %u\n", "data version", iDataVersion); + return 0; } /* ** Print the current sqlite3_errmsg() value to stderr and return 1. */ static int shellDatabaseError(sqlite3 *db){ - const char *zErr = sqlite3_errmsg(db); - utf8_printf(stderr, "Error: %s\n", zErr); - return 1; + const char *zErr = sqlite3_errmsg(db); + utf8_printf(stderr, "Error: %s\n", zErr); + return 1; } /* @@ -16687,77 +16687,77 @@ static int shellDatabaseError(sqlite3 *db){ ** Extra whitespace at the end of z[] is ignored. */ static int testcase_glob(const char *zGlob, const char *z){ - int c, c2; - int invert; - int seen; - - while( (c = (*(zGlob++)))!=0 ){ - if( IsSpace(c) ){ - if( !IsSpace(*z) ) return 0; - while( IsSpace(*zGlob) ) zGlob++; - while( IsSpace(*z) ) z++; - }else if( c=='*' ){ - while( (c=(*(zGlob++))) == '*' || c=='?' ){ - if( c=='?' && (*(z++))==0 ) return 0; - } - if( c==0 ){ - return 1; - }else if( c=='[' ){ - while( *z && testcase_glob(zGlob-1,z)==0 ){ - z++; - } - return (*z)!=0; - } - while( (c2 = (*(z++)))!=0 ){ - while( c2!=c ){ - c2 = *(z++); - if( c2==0 ) return 0; - } - if( testcase_glob(zGlob,z) ) return 1; - } - return 0; - }else if( c=='?' ){ - if( (*(z++))==0 ) return 0; - }else if( c=='[' ){ - int prior_c = 0; - seen = 0; - invert = 0; - c = *(z++); - if( c==0 ) return 0; - c2 = *(zGlob++); - if( c2=='^' ){ - invert = 1; - c2 = *(zGlob++); - } - if( c2==']' ){ - if( c==']' ) seen = 1; - c2 = *(zGlob++); - } - while( c2 && c2!=']' ){ - if( c2=='-' && zGlob[0]!=']' && zGlob[0]!=0 && prior_c>0 ){ - c2 = *(zGlob++); - if( c>=prior_c && c<=c2 ) seen = 1; - prior_c = 0; - }else{ - if( c==c2 ){ - seen = 1; - } - prior_c = c2; - } - c2 = *(zGlob++); - } - if( c2==0 || (seen ^ invert)==0 ) return 0; - }else if( c=='#' ){ - if( (z[0]=='-' || z[0]=='+') && IsDigit(z[1]) ) z++; - if( !IsDigit(z[0]) ) return 0; - z++; - while( IsDigit(z[0]) ){ z++; } + int c, c2; + int invert; + int seen; + + while( (c = (*(zGlob++)))!=0 ){ + if( IsSpace(c) ){ + if( !IsSpace(*z) ) return 0; + while( IsSpace(*zGlob) ) zGlob++; + while( IsSpace(*z) ) z++; + }else if( c=='*' ){ + while( (c=(*(zGlob++))) == '*' || c=='?' ){ + if( c=='?' && (*(z++))==0 ) return 0; + } + if( c==0 ){ + return 1; + }else if( c=='[' ){ + while( *z && testcase_glob(zGlob-1,z)==0 ){ + z++; + } + return (*z)!=0; + } + while( (c2 = (*(z++)))!=0 ){ + while( c2!=c ){ + c2 = *(z++); + if( c2==0 ) return 0; + } + if( testcase_glob(zGlob,z) ) return 1; + } + return 0; + }else if( c=='?' ){ + if( (*(z++))==0 ) return 0; + }else if( c=='[' ){ + int prior_c = 0; + seen = 0; + invert = 0; + c = *(z++); + if( c==0 ) return 0; + c2 = *(zGlob++); + if( c2=='^' ){ + invert = 1; + c2 = *(zGlob++); + } + if( c2==']' ){ + if( c==']' ) seen = 1; + c2 = *(zGlob++); + } + while( c2 && c2!=']' ){ + if( c2=='-' && zGlob[0]!=']' && zGlob[0]!=0 && prior_c>0 ){ + c2 = *(zGlob++); + if( c>=prior_c && c<=c2 ) seen = 1; + prior_c = 0; }else{ - if( c!=(*(z++)) ) return 0; - } + if( c==c2 ){ + seen = 1; + } + prior_c = c2; + } + c2 = *(zGlob++); + } + if( c2==0 || (seen ^ invert)==0 ) return 0; + }else if( c=='#' ){ + if( (z[0]=='-' || z[0]=='+') && IsDigit(z[1]) ) z++; + if( !IsDigit(z[0]) ) return 0; + z++; + while( IsDigit(z[0]) ){ z++; } + }else{ + if( c!=(*(z++)) ) return 0; } - while( IsSpace(*z) ){ z++; } - return *z==0; + } + while( IsSpace(*z) ){ z++; } + return *z==0; } @@ -16766,25 +16766,25 @@ static int testcase_glob(const char *zGlob, const char *z){ ** initial "-" characters. */ static int optionMatch(const char *zStr, const char *zOpt){ - if( zStr[0]!='-' ) return 0; - zStr++; - if( zStr[0]=='-' ) zStr++; - return strcmp(zStr, zOpt)==0; + if( zStr[0]!='-' ) return 0; + zStr++; + if( zStr[0]=='-' ) zStr++; + return strcmp(zStr, zOpt)==0; } /* ** Delete a file. */ int shellDeleteFile(const char *zFilename){ - int rc; + int rc; #ifdef _WIN32 - wchar_t *z = sqlite3_win32_utf8_to_unicode(zFilename); - rc = _wunlink(z); - sqlite3_free(z); + wchar_t *z = sqlite3_win32_utf8_to_unicode(zFilename); + rc = _wunlink(z); + sqlite3_free(z); #else - rc = unlink(zFilename); + rc = unlink(zFilename); #endif - return rc; + return rc; } /* @@ -16792,45 +16792,45 @@ int shellDeleteFile(const char *zFilename){ ** memory used to hold the name of the temp file. */ static void clearTempFile(ShellState *p){ - if( p->zTempFile==0 ) return; - if( p->doXdgOpen ) return; - if( shellDeleteFile(p->zTempFile) ) return; - sqlite3_free(p->zTempFile); - p->zTempFile = 0; + if( p->zTempFile==0 ) return; + if( p->doXdgOpen ) return; + if( shellDeleteFile(p->zTempFile) ) return; + sqlite3_free(p->zTempFile); + p->zTempFile = 0; } /* ** Create a new temp file name with the given suffix. */ static void newTempFile(ShellState *p, const char *zSuffix){ - clearTempFile(p); - sqlite3_free(p->zTempFile); - p->zTempFile = 0; - if( p->db ){ - sqlite3_file_control(p->db, 0, SQLITE_FCNTL_TEMPFILENAME, &p->zTempFile); - } - if( p->zTempFile==0 ){ - /* If p->db is an in-memory database then the TEMPFILENAME file-control + clearTempFile(p); + sqlite3_free(p->zTempFile); + p->zTempFile = 0; + if( p->db ){ + sqlite3_file_control(p->db, 0, SQLITE_FCNTL_TEMPFILENAME, &p->zTempFile); + } + if( p->zTempFile==0 ){ + /* If p->db is an in-memory database then the TEMPFILENAME file-control ** will not work and we will need to fallback to guessing */ - char *zTemp; - sqlite3_uint64 r; - sqlite3_randomness(sizeof(r), &r); - zTemp = getenv("TEMP"); - if( zTemp==0 ) zTemp = getenv("TMP"); - if( zTemp==0 ){ + char *zTemp; + sqlite3_uint64 r; + sqlite3_randomness(sizeof(r), &r); + zTemp = getenv("TEMP"); + if( zTemp==0 ) zTemp = getenv("TMP"); + if( zTemp==0 ){ #ifdef _WIN32 - zTemp = "\\tmp"; + zTemp = "\\tmp"; #else - zTemp = "/tmp"; + zTemp = "/tmp"; #endif - } - p->zTempFile = sqlite3_mprintf("%s/temp%llx.%s", zTemp, r, zSuffix); - }else{ - p->zTempFile = sqlite3_mprintf("%z.%s", p->zTempFile, zSuffix); - } - if( p->zTempFile==0 ){ - shell_out_of_memory(); } + p->zTempFile = sqlite3_mprintf("%s/temp%llx.%s", zTemp, r, zSuffix); + }else{ + p->zTempFile = sqlite3_mprintf("%z.%s", p->zTempFile, zSuffix); + } + if( p->zTempFile==0 ){ + shell_out_of_memory(); + } } @@ -16850,40 +16850,40 @@ static void newTempFile(ShellState *p, const char *zSuffix){ ** is the default collation sequence of the parent column. */ static void shellFkeyCollateClause( - sqlite3_context *pCtx, - int nVal, - sqlite3_value **apVal + sqlite3_context *pCtx, + int nVal, + sqlite3_value **apVal ){ - sqlite3 *db = sqlite3_context_db_handle(pCtx); - const char *zParent; - const char *zParentCol; - const char *zParentSeq; - const char *zChild; - const char *zChildCol; - const char *zChildSeq = 0; /* Initialize to avoid false-positive warning */ - int rc; - - assert( nVal==4 ); - zParent = (const char*)sqlite3_value_text(apVal[0]); - zParentCol = (const char*)sqlite3_value_text(apVal[1]); - zChild = (const char*)sqlite3_value_text(apVal[2]); - zChildCol = (const char*)sqlite3_value_text(apVal[3]); - - sqlite3_result_text(pCtx, "", -1, SQLITE_STATIC); + sqlite3 *db = sqlite3_context_db_handle(pCtx); + const char *zParent; + const char *zParentCol; + const char *zParentSeq; + const char *zChild; + const char *zChildCol; + const char *zChildSeq = 0; /* Initialize to avoid false-positive warning */ + int rc; + + assert( nVal==4 ); + zParent = (const char*)sqlite3_value_text(apVal[0]); + zParentCol = (const char*)sqlite3_value_text(apVal[1]); + zChild = (const char*)sqlite3_value_text(apVal[2]); + zChildCol = (const char*)sqlite3_value_text(apVal[3]); + + sqlite3_result_text(pCtx, "", -1, SQLITE_STATIC); + rc = sqlite3_table_column_metadata( + db, "main", zParent, zParentCol, 0, &zParentSeq, 0, 0, 0 + ); + if( rc==SQLITE_OK ){ rc = sqlite3_table_column_metadata( - db, "main", zParent, zParentCol, 0, &zParentSeq, 0, 0, 0 + db, "main", zChild, zChildCol, 0, &zChildSeq, 0, 0, 0 ); - if( rc==SQLITE_OK ){ - rc = sqlite3_table_column_metadata( - db, "main", zChild, zChildCol, 0, &zChildSeq, 0, 0, 0 - ); - } + } - if( rc==SQLITE_OK && sqlite3_stricmp(zParentSeq, zChildSeq) ){ - char *z = sqlite3_mprintf(" COLLATE %s", zParentSeq); - sqlite3_result_text(pCtx, z, -1, SQLITE_TRANSIENT); - sqlite3_free(z); - } + if( rc==SQLITE_OK && sqlite3_stricmp(zParentSeq, zChildSeq) ){ + char *z = sqlite3_mprintf(" COLLATE %s", zParentSeq); + sqlite3_result_text(pCtx, z, -1, SQLITE_TRANSIENT); + sqlite3_free(z); + } } @@ -16891,20 +16891,20 @@ static void shellFkeyCollateClause( ** The implementation of dot-command ".lint fkey-indexes". */ static int lintFkeyIndexes( - ShellState *pState, /* Current shell tool state */ - char **azArg, /* Array of arguments passed to dot command */ - int nArg /* Number of entries in azArg[] */ + ShellState *pState, /* Current shell tool state */ + char **azArg, /* Array of arguments passed to dot command */ + int nArg /* Number of entries in azArg[] */ ){ - sqlite3 *db = pState->db; /* Database handle to query "main" db of */ - FILE *out = pState->out; /* Stream to write non-error output to */ - int bVerbose = 0; /* If -verbose is present */ - int bGroupByParent = 0; /* If -groupbyparent is present */ - int i; /* To iterate through azArg[] */ - const char *zIndent = ""; /* How much to indent CREATE INDEX by */ - int rc; /* Return code */ - sqlite3_stmt *pSql = 0; /* Compiled version of SQL statement below */ - - /* + sqlite3 *db = pState->db; /* Database handle to query "main" db of */ + FILE *out = pState->out; /* Stream to write non-error output to */ + int bVerbose = 0; /* If -verbose is present */ + int bGroupByParent = 0; /* If -groupbyparent is present */ + int i; /* To iterate through azArg[] */ + const char *zIndent = ""; /* How much to indent CREATE INDEX by */ + int rc; /* Return code */ + sqlite3_stmt *pSql = 0; /* Compiled version of SQL statement below */ + + /* ** This SELECT statement returns one row for each foreign key constraint ** in the schema of the main database. The column values are: ** @@ -16939,167 +16939,167 @@ static int lintFkeyIndexes( ** ** These six values are used by the C logic below to generate the report. */ - const char *zSql = - "SELECT " - " 'EXPLAIN QUERY PLAN SELECT 1 FROM ' || quote(s.name) || ' WHERE '" - " || group_concat(quote(s.name) || '.' || quote(f.[from]) || '=?' " - " || fkey_collate_clause(" - " f.[table], COALESCE(f.[to], p.[name]), s.name, f.[from]),' AND ')" - ", " - " 'SEARCH ' || s.name || ' USING COVERING INDEX*('" - " || group_concat('*=?', ' AND ') || ')'" - ", " - " s.name || '(' || group_concat(f.[from], ', ') || ')'" - ", " - " f.[table] || '(' || group_concat(COALESCE(f.[to], p.[name])) || ')'" - ", " - " 'CREATE INDEX ' || quote(s.name ||'_'|| group_concat(f.[from], '_'))" - " || ' ON ' || quote(s.name) || '('" - " || group_concat(quote(f.[from]) ||" - " fkey_collate_clause(" - " f.[table], COALESCE(f.[to], p.[name]), s.name, f.[from]), ', ')" - " || ');'" - ", " - " f.[table] " - "FROM sqlite_schema AS s, pragma_foreign_key_list(s.name) AS f " - "LEFT JOIN pragma_table_info AS p ON (pk-1=seq AND p.arg=f.[table]) " - "GROUP BY s.name, f.id " - "ORDER BY (CASE WHEN ? THEN f.[table] ELSE s.name END)" - ; - const char *zGlobIPK = "SEARCH * USING INTEGER PRIMARY KEY (rowid=?)"; - - for(i=2; i1 && sqlite3_strnicmp("-verbose", azArg[i], n)==0 ){ - bVerbose = 1; - } - else if( n>1 && sqlite3_strnicmp("-groupbyparent", azArg[i], n)==0 ){ - bGroupByParent = 1; - zIndent = " "; + const char *zSql = + "SELECT " + " 'EXPLAIN QUERY PLAN SELECT 1 FROM ' || quote(s.name) || ' WHERE '" + " || group_concat(quote(s.name) || '.' || quote(f.[from]) || '=?' " + " || fkey_collate_clause(" + " f.[table], COALESCE(f.[to], p.[name]), s.name, f.[from]),' AND ')" + ", " + " 'SEARCH ' || s.name || ' USING COVERING INDEX*('" + " || group_concat('*=?', ' AND ') || ')'" + ", " + " s.name || '(' || group_concat(f.[from], ', ') || ')'" + ", " + " f.[table] || '(' || group_concat(COALESCE(f.[to], p.[name])) || ')'" + ", " + " 'CREATE INDEX ' || quote(s.name ||'_'|| group_concat(f.[from], '_'))" + " || ' ON ' || quote(s.name) || '('" + " || group_concat(quote(f.[from]) ||" + " fkey_collate_clause(" + " f.[table], COALESCE(f.[to], p.[name]), s.name, f.[from]), ', ')" + " || ');'" + ", " + " f.[table] " + "FROM sqlite_schema AS s, pragma_foreign_key_list(s.name) AS f " + "LEFT JOIN pragma_table_info AS p ON (pk-1=seq AND p.arg=f.[table]) " + "GROUP BY s.name, f.id " + "ORDER BY (CASE WHEN ? THEN f.[table] ELSE s.name END)" + ; + const char *zGlobIPK = "SEARCH * USING INTEGER PRIMARY KEY (rowid=?)"; + + for(i=2; i1 && sqlite3_strnicmp("-verbose", azArg[i], n)==0 ){ + bVerbose = 1; + } + else if( n>1 && sqlite3_strnicmp("-groupbyparent", azArg[i], n)==0 ){ + bGroupByParent = 1; + zIndent = " "; + } + else{ + raw_printf(stderr, "Usage: %s %s ?-verbose? ?-groupbyparent?\n", + azArg[0], azArg[1] + ); + return SQLITE_ERROR; + } + } + + /* Register the fkey_collate_clause() SQL function */ + rc = sqlite3_create_function(db, "fkey_collate_clause", 4, SQLITE_UTF8, + 0, shellFkeyCollateClause, 0, 0 + ); + + + if( rc==SQLITE_OK ){ + rc = sqlite3_prepare_v2(db, zSql, -1, &pSql, 0); + } + if( rc==SQLITE_OK ){ + sqlite3_bind_int(pSql, 1, bGroupByParent); + } + + if( rc==SQLITE_OK ){ + int rc2; + char *zPrev = 0; + while( SQLITE_ROW==sqlite3_step(pSql) ){ + int res = -1; + sqlite3_stmt *pExplain = 0; + const char *zEQP = (const char*)sqlite3_column_text(pSql, 0); + const char *zGlob = (const char*)sqlite3_column_text(pSql, 1); + const char *zFrom = (const char*)sqlite3_column_text(pSql, 2); + const char *zTarget = (const char*)sqlite3_column_text(pSql, 3); + const char *zCI = (const char*)sqlite3_column_text(pSql, 4); + const char *zParent = (const char*)sqlite3_column_text(pSql, 5); + + rc = sqlite3_prepare_v2(db, zEQP, -1, &pExplain, 0); + if( rc!=SQLITE_OK ) break; + if( SQLITE_ROW==sqlite3_step(pExplain) ){ + const char *zPlan = (const char*)sqlite3_column_text(pExplain, 3); + res = ( + 0==sqlite3_strglob(zGlob, zPlan) + || 0==sqlite3_strglob(zGlobIPK, zPlan) + ); + } + rc = sqlite3_finalize(pExplain); + if( rc!=SQLITE_OK ) break; + + if( res<0 ){ + raw_printf(stderr, "Error: internal error"); + break; + }else{ + if( bGroupByParent + && (bVerbose || res==0) + && (zPrev==0 || sqlite3_stricmp(zParent, zPrev)) + ){ + raw_printf(out, "-- Parent table %s\n", zParent); + sqlite3_free(zPrev); + zPrev = sqlite3_mprintf("%s", zParent); } - else{ - raw_printf(stderr, "Usage: %s %s ?-verbose? ?-groupbyparent?\n", - azArg[0], azArg[1] - ); - return SQLITE_ERROR; + + if( res==0 ){ + raw_printf(out, "%s%s --> %s\n", zIndent, zCI, zTarget); + }else if( bVerbose ){ + raw_printf(out, "%s/* no extra indexes required for %s -> %s */\n", + zIndent, zFrom, zTarget + ); } + } } + sqlite3_free(zPrev); - /* Register the fkey_collate_clause() SQL function */ - rc = sqlite3_create_function(db, "fkey_collate_clause", 4, SQLITE_UTF8, - 0, shellFkeyCollateClause, 0, 0 - ); - - - if( rc==SQLITE_OK ){ - rc = sqlite3_prepare_v2(db, zSql, -1, &pSql, 0); - } - if( rc==SQLITE_OK ){ - sqlite3_bind_int(pSql, 1, bGroupByParent); + if( rc!=SQLITE_OK ){ + raw_printf(stderr, "%s\n", sqlite3_errmsg(db)); } - if( rc==SQLITE_OK ){ - int rc2; - char *zPrev = 0; - while( SQLITE_ROW==sqlite3_step(pSql) ){ - int res = -1; - sqlite3_stmt *pExplain = 0; - const char *zEQP = (const char*)sqlite3_column_text(pSql, 0); - const char *zGlob = (const char*)sqlite3_column_text(pSql, 1); - const char *zFrom = (const char*)sqlite3_column_text(pSql, 2); - const char *zTarget = (const char*)sqlite3_column_text(pSql, 3); - const char *zCI = (const char*)sqlite3_column_text(pSql, 4); - const char *zParent = (const char*)sqlite3_column_text(pSql, 5); - - rc = sqlite3_prepare_v2(db, zEQP, -1, &pExplain, 0); - if( rc!=SQLITE_OK ) break; - if( SQLITE_ROW==sqlite3_step(pExplain) ){ - const char *zPlan = (const char*)sqlite3_column_text(pExplain, 3); - res = ( - 0==sqlite3_strglob(zGlob, zPlan) - || 0==sqlite3_strglob(zGlobIPK, zPlan) - ); - } - rc = sqlite3_finalize(pExplain); - if( rc!=SQLITE_OK ) break; - - if( res<0 ){ - raw_printf(stderr, "Error: internal error"); - break; - }else{ - if( bGroupByParent - && (bVerbose || res==0) - && (zPrev==0 || sqlite3_stricmp(zParent, zPrev)) - ){ - raw_printf(out, "-- Parent table %s\n", zParent); - sqlite3_free(zPrev); - zPrev = sqlite3_mprintf("%s", zParent); - } - - if( res==0 ){ - raw_printf(out, "%s%s --> %s\n", zIndent, zCI, zTarget); - }else if( bVerbose ){ - raw_printf(out, "%s/* no extra indexes required for %s -> %s */\n", - zIndent, zFrom, zTarget - ); - } - } - } - sqlite3_free(zPrev); - - if( rc!=SQLITE_OK ){ - raw_printf(stderr, "%s\n", sqlite3_errmsg(db)); - } - - rc2 = sqlite3_finalize(pSql); - if( rc==SQLITE_OK && rc2!=SQLITE_OK ){ - rc = rc2; - raw_printf(stderr, "%s\n", sqlite3_errmsg(db)); - } - }else{ - raw_printf(stderr, "%s\n", sqlite3_errmsg(db)); + rc2 = sqlite3_finalize(pSql); + if( rc==SQLITE_OK && rc2!=SQLITE_OK ){ + rc = rc2; + raw_printf(stderr, "%s\n", sqlite3_errmsg(db)); } + }else{ + raw_printf(stderr, "%s\n", sqlite3_errmsg(db)); + } - return rc; + return rc; } /* ** Implementation of ".lint" dot command. */ static int lintDotCommand( - ShellState *pState, /* Current shell tool state */ - char **azArg, /* Array of arguments passed to dot command */ - int nArg /* Number of entries in azArg[] */ + ShellState *pState, /* Current shell tool state */ + char **azArg, /* Array of arguments passed to dot command */ + int nArg /* Number of entries in azArg[] */ ){ - int n; - n = (nArg>=2 ? strlen30(azArg[1]) : 0); - if( n<1 || sqlite3_strnicmp(azArg[1], "fkey-indexes", n) ) goto usage; - return lintFkeyIndexes(pState, azArg, nArg); - -usage: - raw_printf(stderr, "Usage %s sub-command ?switches...?\n", azArg[0]); - raw_printf(stderr, "Where sub-commands are:\n"); - raw_printf(stderr, " fkey-indexes\n"); - return SQLITE_ERROR; + int n; + n = (nArg>=2 ? strlen30(azArg[1]) : 0); + if( n<1 || sqlite3_strnicmp(azArg[1], "fkey-indexes", n) ) goto usage; + return lintFkeyIndexes(pState, azArg, nArg); + + usage: + raw_printf(stderr, "Usage %s sub-command ?switches...?\n", azArg[0]); + raw_printf(stderr, "Where sub-commands are:\n"); + raw_printf(stderr, " fkey-indexes\n"); + return SQLITE_ERROR; } #if !defined SQLITE_OMIT_VIRTUALTABLE static void shellPrepare( - sqlite3 *db, - int *pRc, - const char *zSql, - sqlite3_stmt **ppStmt + sqlite3 *db, + int *pRc, + const char *zSql, + sqlite3_stmt **ppStmt ){ - *ppStmt = 0; - if( *pRc==SQLITE_OK ){ - int rc = sqlite3_prepare_v2(db, zSql, -1, ppStmt, 0); - if( rc!=SQLITE_OK ){ - raw_printf(stderr, "sql error: %s (%d)\n", - sqlite3_errmsg(db), sqlite3_errcode(db) - ); - *pRc = rc; - } + *ppStmt = 0; + if( *pRc==SQLITE_OK ){ + int rc = sqlite3_prepare_v2(db, zSql, -1, ppStmt, 0); + if( rc!=SQLITE_OK ){ + raw_printf(stderr, "sql error: %s (%d)\n", + sqlite3_errmsg(db), sqlite3_errcode(db) + ); + *pRc = rc; } + } } /* @@ -17110,26 +17110,26 @@ static void shellPrepare( ** nuisance compiler warnings about "defined but not used". */ void shellPreparePrintf( - sqlite3 *db, - int *pRc, - sqlite3_stmt **ppStmt, - const char *zFmt, - ... + sqlite3 *db, + int *pRc, + sqlite3_stmt **ppStmt, + const char *zFmt, + ... ){ - *ppStmt = 0; - if( *pRc==SQLITE_OK ){ - va_list ap; - char *z; - va_start(ap, zFmt); - z = sqlite3_vmprintf(zFmt, ap); - va_end(ap); - if( z==0 ){ - *pRc = SQLITE_NOMEM; - }else{ - shellPrepare(db, pRc, z, ppStmt); - sqlite3_free(z); - } + *ppStmt = 0; + if( *pRc==SQLITE_OK ){ + va_list ap; + char *z; + va_start(ap, zFmt); + z = sqlite3_vmprintf(zFmt, ap); + va_end(ap); + if( z==0 ){ + *pRc = SQLITE_NOMEM; + }else{ + shellPrepare(db, pRc, z, ppStmt); + sqlite3_free(z); } + } } /* Finalize the prepared statement created using shellPreparePrintf(). @@ -17139,19 +17139,19 @@ void shellPreparePrintf( ** nuisance compiler warnings about "defined but not used". */ void shellFinalize( - int *pRc, - sqlite3_stmt *pStmt + int *pRc, + sqlite3_stmt *pStmt ){ - if( pStmt ){ - sqlite3 *db = sqlite3_db_handle(pStmt); - int rc = sqlite3_finalize(pStmt); - if( *pRc==SQLITE_OK ){ - if( rc!=SQLITE_OK ){ - raw_printf(stderr, "SQL error: %s\n", sqlite3_errmsg(db)); - } - *pRc = rc; - } + if( pStmt ){ + sqlite3 *db = sqlite3_db_handle(pStmt); + int rc = sqlite3_finalize(pStmt); + if( *pRc==SQLITE_OK ){ + if( rc!=SQLITE_OK ){ + raw_printf(stderr, "SQL error: %s\n", sqlite3_errmsg(db)); + } + *pRc = rc; } + } } /* Reset the prepared statement created using shellPreparePrintf(). @@ -17161,17 +17161,17 @@ void shellFinalize( ** nuisance compiler warnings about "defined but not used". */ void shellReset( - int *pRc, - sqlite3_stmt *pStmt + int *pRc, + sqlite3_stmt *pStmt ){ - int rc = sqlite3_reset(pStmt); - if( *pRc==SQLITE_OK ){ - if( rc!=SQLITE_OK ){ - sqlite3 *db = sqlite3_db_handle(pStmt); - raw_printf(stderr, "SQL error: %s\n", sqlite3_errmsg(db)); - } - *pRc = rc; + int rc = sqlite3_reset(pStmt); + if( *pRc==SQLITE_OK ){ + if( rc!=SQLITE_OK ){ + sqlite3 *db = sqlite3_db_handle(pStmt); + raw_printf(stderr, "SQL error: %s\n", sqlite3_errmsg(db)); } + *pRc = rc; + } } #endif /* !defined SQLITE_OMIT_VIRTUALTABLE */ @@ -17184,48 +17184,48 @@ void shellReset( */ typedef struct ArCommand ArCommand; struct ArCommand { - u8 eCmd; /* An AR_CMD_* value */ - u8 bVerbose; /* True if --verbose */ - u8 bZip; /* True if the archive is a ZIP */ - u8 bDryRun; /* True if --dry-run */ - u8 bAppend; /* True if --append */ - u8 bGlob; /* True if --glob */ - u8 fromCmdLine; /* Run from -A instead of .archive */ - int nArg; /* Number of command arguments */ - char *zSrcTable; /* "sqlar", "zipfile($file)" or "zip" */ - const char *zFile; /* --file argument, or NULL */ - const char *zDir; /* --directory argument, or NULL */ - char **azArg; /* Array of command arguments */ - ShellState *p; /* Shell state */ - sqlite3 *db; /* Database containing the archive */ + u8 eCmd; /* An AR_CMD_* value */ + u8 bVerbose; /* True if --verbose */ + u8 bZip; /* True if the archive is a ZIP */ + u8 bDryRun; /* True if --dry-run */ + u8 bAppend; /* True if --append */ + u8 bGlob; /* True if --glob */ + u8 fromCmdLine; /* Run from -A instead of .archive */ + int nArg; /* Number of command arguments */ + char *zSrcTable; /* "sqlar", "zipfile($file)" or "zip" */ + const char *zFile; /* --file argument, or NULL */ + const char *zDir; /* --directory argument, or NULL */ + char **azArg; /* Array of command arguments */ + ShellState *p; /* Shell state */ + sqlite3 *db; /* Database containing the archive */ }; /* ** Print a usage message for the .ar command to stderr and return SQLITE_ERROR. */ static int arUsage(FILE *f){ - showHelp(f,"archive"); - return SQLITE_ERROR; + showHelp(f,"archive"); + return SQLITE_ERROR; } /* -** Print an error message for the .ar command to stderr and return +** Print an error message for the .ar command to stderr and return ** SQLITE_ERROR. */ static int arErrorMsg(ArCommand *pAr, const char *zFmt, ...){ - va_list ap; - char *z; - va_start(ap, zFmt); - z = sqlite3_vmprintf(zFmt, ap); - va_end(ap); - utf8_printf(stderr, "Error: %s\n", z); - if( pAr->fromCmdLine ){ - utf8_printf(stderr, "Use \"-A\" for more help\n"); - }else{ - utf8_printf(stderr, "Use \".archive --help\" for more help\n"); - } - sqlite3_free(z); - return SQLITE_ERROR; + va_list ap; + char *z; + va_start(ap, zFmt); + z = sqlite3_vmprintf(zFmt, ap); + va_end(ap); + utf8_printf(stderr, "Error: %s\n", z); + if( pAr->fromCmdLine ){ + utf8_printf(stderr, "Use \"-A\" for more help\n"); + }else{ + utf8_printf(stderr, "Use \".archive --help\" for more help\n"); + } + sqlite3_free(z); + return SQLITE_ERROR; } /* @@ -17250,185 +17250,185 @@ static int arErrorMsg(ArCommand *pAr, const char *zFmt, ...){ #define AR_SWITCH_GLOB 13 static int arProcessSwitch(ArCommand *pAr, int eSwitch, const char *zArg){ - switch( eSwitch ){ - case AR_CMD_CREATE: - case AR_CMD_EXTRACT: - case AR_CMD_LIST: - case AR_CMD_REMOVE: - case AR_CMD_UPDATE: - case AR_CMD_INSERT: - case AR_CMD_HELP: - if( pAr->eCmd ){ - return arErrorMsg(pAr, "multiple command options"); - } - pAr->eCmd = eSwitch; - break; - - case AR_SWITCH_DRYRUN: - pAr->bDryRun = 1; - break; - case AR_SWITCH_GLOB: - pAr->bGlob = 1; - break; - case AR_SWITCH_VERBOSE: - pAr->bVerbose = 1; - break; - case AR_SWITCH_APPEND: - pAr->bAppend = 1; - /* Fall thru into --file */ - case AR_SWITCH_FILE: - pAr->zFile = zArg; - break; - case AR_SWITCH_DIRECTORY: - pAr->zDir = zArg; - break; - } - - return SQLITE_OK; + switch( eSwitch ){ + case AR_CMD_CREATE: + case AR_CMD_EXTRACT: + case AR_CMD_LIST: + case AR_CMD_REMOVE: + case AR_CMD_UPDATE: + case AR_CMD_INSERT: + case AR_CMD_HELP: + if( pAr->eCmd ){ + return arErrorMsg(pAr, "multiple command options"); + } + pAr->eCmd = eSwitch; + break; + + case AR_SWITCH_DRYRUN: + pAr->bDryRun = 1; + break; + case AR_SWITCH_GLOB: + pAr->bGlob = 1; + break; + case AR_SWITCH_VERBOSE: + pAr->bVerbose = 1; + break; + case AR_SWITCH_APPEND: + pAr->bAppend = 1; + /* Fall thru into --file */ + case AR_SWITCH_FILE: + pAr->zFile = zArg; + break; + case AR_SWITCH_DIRECTORY: + pAr->zDir = zArg; + break; + } + + return SQLITE_OK; } /* ** Parse the command line for an ".ar" command. The results are written into ** structure (*pAr). SQLITE_OK is returned if the command line is parsed -** successfully, otherwise an error message is written to stderr and +** successfully, otherwise an error message is written to stderr and ** SQLITE_ERROR returned. */ static int arParseCommand( - char **azArg, /* Array of arguments passed to dot command */ - int nArg, /* Number of entries in azArg[] */ - ArCommand *pAr /* Populate this object */ + char **azArg, /* Array of arguments passed to dot command */ + int nArg, /* Number of entries in azArg[] */ + ArCommand *pAr /* Populate this object */ ){ - struct ArSwitch { - const char *zLong; - char cShort; - u8 eSwitch; - u8 bArg; - } aSwitch[] = { - { "create", 'c', AR_CMD_CREATE, 0 }, - { "extract", 'x', AR_CMD_EXTRACT, 0 }, - { "insert", 'i', AR_CMD_INSERT, 0 }, - { "list", 't', AR_CMD_LIST, 0 }, - { "remove", 'r', AR_CMD_REMOVE, 0 }, - { "update", 'u', AR_CMD_UPDATE, 0 }, - { "help", 'h', AR_CMD_HELP, 0 }, - { "verbose", 'v', AR_SWITCH_VERBOSE, 0 }, - { "file", 'f', AR_SWITCH_FILE, 1 }, - { "append", 'a', AR_SWITCH_APPEND, 1 }, - { "directory", 'C', AR_SWITCH_DIRECTORY, 1 }, - { "dryrun", 'n', AR_SWITCH_DRYRUN, 0 }, - { "glob", 'g', AR_SWITCH_GLOB, 0 }, - }; - int nSwitch = sizeof(aSwitch) / sizeof(struct ArSwitch); - struct ArSwitch *pEnd = &aSwitch[nSwitch]; - - if( nArg<=1 ){ - utf8_printf(stderr, "Wrong number of arguments. Usage:\n"); - return arUsage(stderr); + struct ArSwitch { + const char *zLong; + char cShort; + u8 eSwitch; + u8 bArg; + } aSwitch[] = { + { "create", 'c', AR_CMD_CREATE, 0 }, + { "extract", 'x', AR_CMD_EXTRACT, 0 }, + { "insert", 'i', AR_CMD_INSERT, 0 }, + { "list", 't', AR_CMD_LIST, 0 }, + { "remove", 'r', AR_CMD_REMOVE, 0 }, + { "update", 'u', AR_CMD_UPDATE, 0 }, + { "help", 'h', AR_CMD_HELP, 0 }, + { "verbose", 'v', AR_SWITCH_VERBOSE, 0 }, + { "file", 'f', AR_SWITCH_FILE, 1 }, + { "append", 'a', AR_SWITCH_APPEND, 1 }, + { "directory", 'C', AR_SWITCH_DIRECTORY, 1 }, + { "dryrun", 'n', AR_SWITCH_DRYRUN, 0 }, + { "glob", 'g', AR_SWITCH_GLOB, 0 }, + }; + int nSwitch = sizeof(aSwitch) / sizeof(struct ArSwitch); + struct ArSwitch *pEnd = &aSwitch[nSwitch]; + + if( nArg<=1 ){ + utf8_printf(stderr, "Wrong number of arguments. Usage:\n"); + return arUsage(stderr); + }else{ + char *z = azArg[1]; + if( z[0]!='-' ){ + /* Traditional style [tar] invocation */ + int i; + int iArg = 2; + for(i=0; z[i]; i++){ + const char *zArg = 0; + struct ArSwitch *pOpt; + for(pOpt=&aSwitch[0]; pOptcShort ) break; + } + if( pOpt==pEnd ){ + return arErrorMsg(pAr, "unrecognized option: %c", z[i]); + } + if( pOpt->bArg ){ + if( iArg>=nArg ){ + return arErrorMsg(pAr, "option requires an argument: %c",z[i]); + } + zArg = azArg[iArg++]; + } + if( arProcessSwitch(pAr, pOpt->eSwitch, zArg) ) return SQLITE_ERROR; + } + pAr->nArg = nArg-iArg; + if( pAr->nArg>0 ){ + pAr->azArg = &azArg[iArg]; + } }else{ - char *z = azArg[1]; + /* Non-traditional invocation */ + int iArg; + for(iArg=1; iArgcShort ) break; - } - if( pOpt==pEnd ){ - return arErrorMsg(pAr, "unrecognized option: %c", z[i]); - } - if( pOpt->bArg ){ - if( iArg>=nArg ){ - return arErrorMsg(pAr, "option requires an argument: %c",z[i]); - } - zArg = azArg[iArg++]; + /* All remaining command line words are command arguments. */ + pAr->azArg = &azArg[iArg]; + pAr->nArg = nArg-iArg; + break; + } + n = strlen30(z); + + if( z[1]!='-' ){ + int i; + /* One or more short options */ + for(i=1; icShort ) break; + } + if( pOpt==pEnd ){ + return arErrorMsg(pAr, "unrecognized option: %c", z[i]); + } + if( pOpt->bArg ){ + if( i<(n-1) ){ + zArg = &z[i+1]; + i = n; + }else{ + if( iArg>=(nArg-1) ){ + return arErrorMsg(pAr, "option requires an argument: %c", + z[i]); } - if( arProcessSwitch(pAr, pOpt->eSwitch, zArg) ) return SQLITE_ERROR; + zArg = azArg[++iArg]; + } } - pAr->nArg = nArg-iArg; - if( pAr->nArg>0 ){ - pAr->azArg = &azArg[iArg]; - } - }else{ - /* Non-traditional invocation */ - int iArg; - for(iArg=1; iArgazArg = &azArg[iArg]; - pAr->nArg = nArg-iArg; - break; - } - n = strlen30(z); - - if( z[1]!='-' ){ - int i; - /* One or more short options */ - for(i=1; icShort ) break; - } - if( pOpt==pEnd ){ - return arErrorMsg(pAr, "unrecognized option: %c", z[i]); - } - if( pOpt->bArg ){ - if( i<(n-1) ){ - zArg = &z[i+1]; - i = n; - }else{ - if( iArg>=(nArg-1) ){ - return arErrorMsg(pAr, "option requires an argument: %c", - z[i]); - } - zArg = azArg[++iArg]; - } - } - if( arProcessSwitch(pAr, pOpt->eSwitch, zArg) ) return SQLITE_ERROR; - } - }else if( z[2]=='\0' ){ - /* A -- option, indicating that all remaining command line words + if( arProcessSwitch(pAr, pOpt->eSwitch, zArg) ) return SQLITE_ERROR; + } + }else if( z[2]=='\0' ){ + /* A -- option, indicating that all remaining command line words ** are command arguments. */ - pAr->azArg = &azArg[iArg+1]; - pAr->nArg = nArg-iArg-1; - break; - }else{ - /* A long option */ - const char *zArg = 0; /* Argument for option, if any */ - struct ArSwitch *pMatch = 0; /* Matching option */ - struct ArSwitch *pOpt; /* Iterator */ - for(pOpt=&aSwitch[0]; pOptzLong; - if( (n-2)<=strlen30(zLong) && 0==memcmp(&z[2], zLong, n-2) ){ - if( pMatch ){ - return arErrorMsg(pAr, "ambiguous option: %s",z); - }else{ - pMatch = pOpt; - } - } - } - - if( pMatch==0 ){ - return arErrorMsg(pAr, "unrecognized option: %s", z); - } - if( pMatch->bArg ){ - if( iArg>=(nArg-1) ){ - return arErrorMsg(pAr, "option requires an argument: %s", z); - } - zArg = azArg[++iArg]; - } - if( arProcessSwitch(pAr, pMatch->eSwitch, zArg) ) return SQLITE_ERROR; - } + pAr->azArg = &azArg[iArg+1]; + pAr->nArg = nArg-iArg-1; + break; + }else{ + /* A long option */ + const char *zArg = 0; /* Argument for option, if any */ + struct ArSwitch *pMatch = 0; /* Matching option */ + struct ArSwitch *pOpt; /* Iterator */ + for(pOpt=&aSwitch[0]; pOptzLong; + if( (n-2)<=strlen30(zLong) && 0==memcmp(&z[2], zLong, n-2) ){ + if( pMatch ){ + return arErrorMsg(pAr, "ambiguous option: %s",z); + }else{ + pMatch = pOpt; + } + } + } + + if( pMatch==0 ){ + return arErrorMsg(pAr, "unrecognized option: %s", z); + } + if( pMatch->bArg ){ + if( iArg>=(nArg-1) ){ + return arErrorMsg(pAr, "option requires an argument: %s", z); } + zArg = azArg[++iArg]; + } + if( arProcessSwitch(pAr, pMatch->eSwitch, zArg) ) return SQLITE_ERROR; } + } } + } - return SQLITE_OK; + return SQLITE_OK; } /* @@ -17446,35 +17446,35 @@ static int arParseCommand( ** Linux. */ static int arCheckEntries(ArCommand *pAr){ - int rc = SQLITE_OK; - if( pAr->nArg ){ - int i, j; - sqlite3_stmt *pTest = 0; - const char *zSel = (pAr->bGlob) - ? "SELECT name FROM %s WHERE glob($name,name)" - : "SELECT name FROM %s WHERE name=$name"; - - shellPreparePrintf(pAr->db, &rc, &pTest, zSel, pAr->zSrcTable); - j = sqlite3_bind_parameter_index(pTest, "$name"); - for(i=0; inArg && rc==SQLITE_OK; i++){ - char *z = pAr->azArg[i]; - int n = strlen30(z); - int bOk = 0; - while( n>0 && z[n-1]=='/' ) n--; - z[n] = '\0'; - sqlite3_bind_text(pTest, j, z, -1, SQLITE_STATIC); - if( SQLITE_ROW==sqlite3_step(pTest) ){ - bOk = 1; - } - shellReset(&rc, pTest); - if( rc==SQLITE_OK && bOk==0 ){ - utf8_printf(stderr, "not found in archive: %s\n", z); - rc = SQLITE_ERROR; - } - } - shellFinalize(&rc, pTest); + int rc = SQLITE_OK; + if( pAr->nArg ){ + int i, j; + sqlite3_stmt *pTest = 0; + const char *zSel = (pAr->bGlob) + ? "SELECT name FROM %s WHERE glob($name,name)" + : "SELECT name FROM %s WHERE name=$name"; + + shellPreparePrintf(pAr->db, &rc, &pTest, zSel, pAr->zSrcTable); + j = sqlite3_bind_parameter_index(pTest, "$name"); + for(i=0; inArg && rc==SQLITE_OK; i++){ + char *z = pAr->azArg[i]; + int n = strlen30(z); + int bOk = 0; + while( n>0 && z[n-1]=='/' ) n--; + z[n] = '\0'; + sqlite3_bind_text(pTest, j, z, -1, SQLITE_STATIC); + if( SQLITE_ROW==sqlite3_step(pTest) ){ + bOk = 1; + } + shellReset(&rc, pTest); + if( rc==SQLITE_OK && bOk==0 ){ + utf8_printf(stderr, "not found in archive: %s\n", z); + rc = SQLITE_ERROR; + } } - return rc; + shellFinalize(&rc, pTest); + } + return rc; } /* @@ -17486,73 +17486,73 @@ static int arCheckEntries(ArCommand *pAr){ ** when pAr->bGlob is false and GLOB match when pAr->bGlob is true. */ static void arWhereClause( - int *pRc, - ArCommand *pAr, - char **pzWhere /* OUT: New WHERE clause */ + int *pRc, + ArCommand *pAr, + char **pzWhere /* OUT: New WHERE clause */ ){ - char *zWhere = 0; - const char *zSameOp = (pAr->bGlob)? "GLOB" : "="; - if( *pRc==SQLITE_OK ){ - if( pAr->nArg==0 ){ - zWhere = sqlite3_mprintf("1"); - }else{ - int i; - const char *zSep = ""; - for(i=0; inArg; i++){ - const char *z = pAr->azArg[i]; - zWhere = sqlite3_mprintf( - "%z%s name %s '%q' OR substr(name,1,%d) %s '%q/'", - zWhere, zSep, zSameOp, z, strlen30(z)+1, zSameOp, z - ); - if( zWhere==0 ){ - *pRc = SQLITE_NOMEM; - break; - } - zSep = " OR "; - } + char *zWhere = 0; + const char *zSameOp = (pAr->bGlob)? "GLOB" : "="; + if( *pRc==SQLITE_OK ){ + if( pAr->nArg==0 ){ + zWhere = sqlite3_mprintf("1"); + }else{ + int i; + const char *zSep = ""; + for(i=0; inArg; i++){ + const char *z = pAr->azArg[i]; + zWhere = sqlite3_mprintf( + "%z%s name %s '%q' OR substr(name,1,%d) %s '%q/'", + zWhere, zSep, zSameOp, z, strlen30(z)+1, zSameOp, z + ); + if( zWhere==0 ){ + *pRc = SQLITE_NOMEM; + break; } + zSep = " OR "; + } } - *pzWhere = zWhere; + } + *pzWhere = zWhere; } /* -** Implementation of .ar "lisT" command. +** Implementation of .ar "lisT" command. */ static int arListCommand(ArCommand *pAr){ - const char *zSql = "SELECT %s FROM %s WHERE %s"; - const char *azCols[] = { - "name", - "lsmode(mode), sz, datetime(mtime, 'unixepoch'), name" - }; - - char *zWhere = 0; - sqlite3_stmt *pSql = 0; - int rc; - - rc = arCheckEntries(pAr); - arWhereClause(&rc, pAr, &zWhere); - - shellPreparePrintf(pAr->db, &rc, &pSql, zSql, azCols[pAr->bVerbose], - pAr->zSrcTable, zWhere); - if( pAr->bDryRun ){ - utf8_printf(pAr->p->out, "%s\n", sqlite3_sql(pSql)); - }else{ - while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSql) ){ - if( pAr->bVerbose ){ - utf8_printf(pAr->p->out, "%s % 10d %s %s\n", - sqlite3_column_text(pSql, 0), - sqlite3_column_int(pSql, 1), - sqlite3_column_text(pSql, 2), - sqlite3_column_text(pSql, 3) - ); - }else{ - utf8_printf(pAr->p->out, "%s\n", sqlite3_column_text(pSql, 0)); - } - } + const char *zSql = "SELECT %s FROM %s WHERE %s"; + const char *azCols[] = { + "name", + "lsmode(mode), sz, datetime(mtime, 'unixepoch'), name" + }; + + char *zWhere = 0; + sqlite3_stmt *pSql = 0; + int rc; + + rc = arCheckEntries(pAr); + arWhereClause(&rc, pAr, &zWhere); + + shellPreparePrintf(pAr->db, &rc, &pSql, zSql, azCols[pAr->bVerbose], + pAr->zSrcTable, zWhere); + if( pAr->bDryRun ){ + utf8_printf(pAr->p->out, "%s\n", sqlite3_sql(pSql)); + }else{ + while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSql) ){ + if( pAr->bVerbose ){ + utf8_printf(pAr->p->out, "%s % 10d %s %s\n", + sqlite3_column_text(pSql, 0), + sqlite3_column_int(pSql, 1), + sqlite3_column_text(pSql, 2), + sqlite3_column_text(pSql, 3) + ); + }else{ + utf8_printf(pAr->p->out, "%s\n", sqlite3_column_text(pSql, 0)); + } } - shellFinalize(&rc, pSql); - sqlite3_free(zWhere); - return rc; + } + shellFinalize(&rc, pSql); + sqlite3_free(zWhere); + return rc; } @@ -17560,132 +17560,132 @@ static int arListCommand(ArCommand *pAr){ ** Implementation of .ar "Remove" command. */ static int arRemoveCommand(ArCommand *pAr){ - int rc = 0; - char *zSql = 0; - char *zWhere = 0; + int rc = 0; + char *zSql = 0; + char *zWhere = 0; - if( pAr->nArg ){ - /* Verify that args actually exist within the archive before proceeding. + if( pAr->nArg ){ + /* Verify that args actually exist within the archive before proceeding. ** And formulate a WHERE clause to match them. */ - rc = arCheckEntries(pAr); - arWhereClause(&rc, pAr, &zWhere); - } - if( rc==SQLITE_OK ){ - zSql = sqlite3_mprintf("DELETE FROM %s WHERE %s;", - pAr->zSrcTable, zWhere); - if( pAr->bDryRun ){ - utf8_printf(pAr->p->out, "%s\n", zSql); + rc = arCheckEntries(pAr); + arWhereClause(&rc, pAr, &zWhere); + } + if( rc==SQLITE_OK ){ + zSql = sqlite3_mprintf("DELETE FROM %s WHERE %s;", + pAr->zSrcTable, zWhere); + if( pAr->bDryRun ){ + utf8_printf(pAr->p->out, "%s\n", zSql); + }else{ + char *zErr = 0; + rc = sqlite3_exec(pAr->db, "SAVEPOINT ar;", 0, 0, 0); + if( rc==SQLITE_OK ){ + rc = sqlite3_exec(pAr->db, zSql, 0, 0, &zErr); + if( rc!=SQLITE_OK ){ + sqlite3_exec(pAr->db, "ROLLBACK TO ar; RELEASE ar;", 0, 0, 0); }else{ - char *zErr = 0; - rc = sqlite3_exec(pAr->db, "SAVEPOINT ar;", 0, 0, 0); - if( rc==SQLITE_OK ){ - rc = sqlite3_exec(pAr->db, zSql, 0, 0, &zErr); - if( rc!=SQLITE_OK ){ - sqlite3_exec(pAr->db, "ROLLBACK TO ar; RELEASE ar;", 0, 0, 0); - }else{ - rc = sqlite3_exec(pAr->db, "RELEASE ar;", 0, 0, 0); - } - } - if( zErr ){ - utf8_printf(stdout, "ERROR: %s\n", zErr); - sqlite3_free(zErr); - } + rc = sqlite3_exec(pAr->db, "RELEASE ar;", 0, 0, 0); } + } + if( zErr ){ + utf8_printf(stdout, "ERROR: %s\n", zErr); + sqlite3_free(zErr); + } } - sqlite3_free(zWhere); - sqlite3_free(zSql); - return rc; + } + sqlite3_free(zWhere); + sqlite3_free(zSql); + return rc; } /* -** Implementation of .ar "eXtract" command. +** Implementation of .ar "eXtract" command. */ static int arExtractCommand(ArCommand *pAr){ - const char *zSql1 = - "SELECT " - " ($dir || name)," - " writefile(($dir || name), %s, mode, mtime) " - "FROM %s WHERE (%s) AND (data IS NULL OR $dirOnly = 0)" - " AND name NOT GLOB '*..[/\\]*'"; - - const char *azExtraArg[] = { - "sqlar_uncompress(data, sz)", - "data" - }; - - sqlite3_stmt *pSql = 0; - int rc = SQLITE_OK; - char *zDir = 0; - char *zWhere = 0; - int i, j; - - /* If arguments are specified, check that they actually exist within + const char *zSql1 = + "SELECT " + " ($dir || name)," + " writefile(($dir || name), %s, mode, mtime) " + "FROM %s WHERE (%s) AND (data IS NULL OR $dirOnly = 0)" + " AND name NOT GLOB '*..[/\\]*'"; + + const char *azExtraArg[] = { + "sqlar_uncompress(data, sz)", + "data" + }; + + sqlite3_stmt *pSql = 0; + int rc = SQLITE_OK; + char *zDir = 0; + char *zWhere = 0; + int i, j; + + /* If arguments are specified, check that they actually exist within ** the archive before proceeding. And formulate a WHERE clause to ** match them. */ - rc = arCheckEntries(pAr); - arWhereClause(&rc, pAr, &zWhere); + rc = arCheckEntries(pAr); + arWhereClause(&rc, pAr, &zWhere); - if( rc==SQLITE_OK ){ - if( pAr->zDir ){ - zDir = sqlite3_mprintf("%s/", pAr->zDir); - }else{ - zDir = sqlite3_mprintf(""); - } - if( zDir==0 ) rc = SQLITE_NOMEM; + if( rc==SQLITE_OK ){ + if( pAr->zDir ){ + zDir = sqlite3_mprintf("%s/", pAr->zDir); + }else{ + zDir = sqlite3_mprintf(""); } + if( zDir==0 ) rc = SQLITE_NOMEM; + } - shellPreparePrintf(pAr->db, &rc, &pSql, zSql1, - azExtraArg[pAr->bZip], pAr->zSrcTable, zWhere - ); + shellPreparePrintf(pAr->db, &rc, &pSql, zSql1, + azExtraArg[pAr->bZip], pAr->zSrcTable, zWhere + ); - if( rc==SQLITE_OK ){ - j = sqlite3_bind_parameter_index(pSql, "$dir"); - sqlite3_bind_text(pSql, j, zDir, -1, SQLITE_STATIC); + if( rc==SQLITE_OK ){ + j = sqlite3_bind_parameter_index(pSql, "$dir"); + sqlite3_bind_text(pSql, j, zDir, -1, SQLITE_STATIC); - /* Run the SELECT statement twice. The first time, writefile() is called + /* Run the SELECT statement twice. The first time, writefile() is called ** for all archive members that should be extracted. The second time, ** only for the directories. This is because the timestamps for ** extracted directories must be reset after they are populated (as ** populating them changes the timestamp). */ - for(i=0; i<2; i++){ - j = sqlite3_bind_parameter_index(pSql, "$dirOnly"); - sqlite3_bind_int(pSql, j, i); - if( pAr->bDryRun ){ - utf8_printf(pAr->p->out, "%s\n", sqlite3_sql(pSql)); - }else{ - while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSql) ){ - if( i==0 && pAr->bVerbose ){ - utf8_printf(pAr->p->out, "%s\n", sqlite3_column_text(pSql, 0)); - } - } - } - shellReset(&rc, pSql); + for(i=0; i<2; i++){ + j = sqlite3_bind_parameter_index(pSql, "$dirOnly"); + sqlite3_bind_int(pSql, j, i); + if( pAr->bDryRun ){ + utf8_printf(pAr->p->out, "%s\n", sqlite3_sql(pSql)); + }else{ + while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSql) ){ + if( i==0 && pAr->bVerbose ){ + utf8_printf(pAr->p->out, "%s\n", sqlite3_column_text(pSql, 0)); + } } - shellFinalize(&rc, pSql); + } + shellReset(&rc, pSql); } + shellFinalize(&rc, pSql); + } - sqlite3_free(zDir); - sqlite3_free(zWhere); - return rc; + sqlite3_free(zDir); + sqlite3_free(zWhere); + return rc; } /* ** Run the SQL statement in zSql. Or if doing a --dryrun, merely print it out. */ static int arExecSql(ArCommand *pAr, const char *zSql){ - int rc; - if( pAr->bDryRun ){ - utf8_printf(pAr->p->out, "%s\n", zSql); - rc = SQLITE_OK; - }else{ - char *zErr = 0; - rc = sqlite3_exec(pAr->db, zSql, 0, 0, &zErr); - if( zErr ){ - utf8_printf(stdout, "ERROR: %s\n", zErr); - sqlite3_free(zErr); - } + int rc; + if( pAr->bDryRun ){ + utf8_printf(pAr->p->out, "%s\n", zSql); + rc = SQLITE_OK; + }else{ + char *zErr = 0; + rc = sqlite3_exec(pAr->db, zSql, 0, 0, &zErr); + if( zErr ){ + utf8_printf(stdout, "ERROR: %s\n", zErr); + sqlite3_free(zErr); } - return rc; + } + return rc; } @@ -17708,220 +17708,220 @@ static int arExecSql(ArCommand *pAr, const char *zSql){ ** "update" only overwrites if the size or mtime or mode has changed. */ static int arCreateOrUpdateCommand( - ArCommand *pAr, /* Command arguments and options */ - int bUpdate, /* true for a --create. */ - int bOnlyIfChanged /* Only update if file has changed */ + ArCommand *pAr, /* Command arguments and options */ + int bUpdate, /* true for a --create. */ + int bOnlyIfChanged /* Only update if file has changed */ ){ - const char *zCreate = - "CREATE TABLE IF NOT EXISTS sqlar(\n" - " name TEXT PRIMARY KEY, -- name of the file\n" - " mode INT, -- access permissions\n" - " mtime INT, -- last modification time\n" - " sz INT, -- original file size\n" - " data BLOB -- compressed content\n" - ")"; - const char *zDrop = "DROP TABLE IF EXISTS sqlar"; - const char *zInsertFmt[2] = { - "REPLACE INTO %s(name,mode,mtime,sz,data)\n" - " SELECT\n" - " %s,\n" - " mode,\n" - " mtime,\n" - " CASE substr(lsmode(mode),1,1)\n" - " WHEN '-' THEN length(data)\n" - " WHEN 'd' THEN 0\n" - " ELSE -1 END,\n" - " sqlar_compress(data)\n" - " FROM fsdir(%Q,%Q) AS disk\n" - " WHERE lsmode(mode) NOT LIKE '?%%'%s;" - , - "REPLACE INTO %s(name,mode,mtime,data)\n" - " SELECT\n" - " %s,\n" - " mode,\n" - " mtime,\n" - " data\n" - " FROM fsdir(%Q,%Q) AS disk\n" - " WHERE lsmode(mode) NOT LIKE '?%%'%s;" - }; - int i; /* For iterating through azFile[] */ - int rc; /* Return code */ - const char *zTab = 0; /* SQL table into which to insert */ - char *zSql; - char zTemp[50]; - char *zExists = 0; - - arExecSql(pAr, "PRAGMA page_size=512"); - rc = arExecSql(pAr, "SAVEPOINT ar;"); - if( rc!=SQLITE_OK ) return rc; - zTemp[0] = 0; - if( pAr->bZip ){ - /* Initialize the zipfile virtual table, if necessary */ - if( pAr->zFile ){ - sqlite3_uint64 r; - sqlite3_randomness(sizeof(r),&r); - sqlite3_snprintf(sizeof(zTemp),zTemp,"zip%016llx",r); - zTab = zTemp; - zSql = sqlite3_mprintf( - "CREATE VIRTUAL TABLE temp.%s USING zipfile(%Q)", - zTab, pAr->zFile - ); - rc = arExecSql(pAr, zSql); - sqlite3_free(zSql); - }else{ - zTab = "zip"; - } + const char *zCreate = + "CREATE TABLE IF NOT EXISTS sqlar(\n" + " name TEXT PRIMARY KEY, -- name of the file\n" + " mode INT, -- access permissions\n" + " mtime INT, -- last modification time\n" + " sz INT, -- original file size\n" + " data BLOB -- compressed content\n" + ")"; + const char *zDrop = "DROP TABLE IF EXISTS sqlar"; + const char *zInsertFmt[2] = { + "REPLACE INTO %s(name,mode,mtime,sz,data)\n" + " SELECT\n" + " %s,\n" + " mode,\n" + " mtime,\n" + " CASE substr(lsmode(mode),1,1)\n" + " WHEN '-' THEN length(data)\n" + " WHEN 'd' THEN 0\n" + " ELSE -1 END,\n" + " sqlar_compress(data)\n" + " FROM fsdir(%Q,%Q) AS disk\n" + " WHERE lsmode(mode) NOT LIKE '?%%'%s;" + , + "REPLACE INTO %s(name,mode,mtime,data)\n" + " SELECT\n" + " %s,\n" + " mode,\n" + " mtime,\n" + " data\n" + " FROM fsdir(%Q,%Q) AS disk\n" + " WHERE lsmode(mode) NOT LIKE '?%%'%s;" + }; + int i; /* For iterating through azFile[] */ + int rc; /* Return code */ + const char *zTab = 0; /* SQL table into which to insert */ + char *zSql; + char zTemp[50]; + char *zExists = 0; + + arExecSql(pAr, "PRAGMA page_size=512"); + rc = arExecSql(pAr, "SAVEPOINT ar;"); + if( rc!=SQLITE_OK ) return rc; + zTemp[0] = 0; + if( pAr->bZip ){ + /* Initialize the zipfile virtual table, if necessary */ + if( pAr->zFile ){ + sqlite3_uint64 r; + sqlite3_randomness(sizeof(r),&r); + sqlite3_snprintf(sizeof(zTemp),zTemp,"zip%016llx",r); + zTab = zTemp; + zSql = sqlite3_mprintf( + "CREATE VIRTUAL TABLE temp.%s USING zipfile(%Q)", + zTab, pAr->zFile + ); + rc = arExecSql(pAr, zSql); + sqlite3_free(zSql); }else{ - /* Initialize the table for an SQLAR */ - zTab = "sqlar"; - if( bUpdate==0 ){ - rc = arExecSql(pAr, zDrop); - if( rc!=SQLITE_OK ) goto end_ar_transaction; - } - rc = arExecSql(pAr, zCreate); - } - if( bOnlyIfChanged ){ - zExists = sqlite3_mprintf( - " AND NOT EXISTS(" - "SELECT 1 FROM %s AS mem" - " WHERE mem.name=disk.name" - " AND mem.mtime=disk.mtime" - " AND mem.mode=disk.mode)", zTab); - }else{ - zExists = sqlite3_mprintf(""); - } - if( zExists==0 ) rc = SQLITE_NOMEM; - for(i=0; inArg && rc==SQLITE_OK; i++){ - char *zSql2 = sqlite3_mprintf(zInsertFmt[pAr->bZip], zTab, - pAr->bVerbose ? "shell_putsnl(name)" : "name", - pAr->azArg[i], pAr->zDir, zExists); - rc = arExecSql(pAr, zSql2); - sqlite3_free(zSql2); - } + zTab = "zip"; + } + }else{ + /* Initialize the table for an SQLAR */ + zTab = "sqlar"; + if( bUpdate==0 ){ + rc = arExecSql(pAr, zDrop); + if( rc!=SQLITE_OK ) goto end_ar_transaction; + } + rc = arExecSql(pAr, zCreate); + } + if( bOnlyIfChanged ){ + zExists = sqlite3_mprintf( + " AND NOT EXISTS(" + "SELECT 1 FROM %s AS mem" + " WHERE mem.name=disk.name" + " AND mem.mtime=disk.mtime" + " AND mem.mode=disk.mode)", zTab); + }else{ + zExists = sqlite3_mprintf(""); + } + if( zExists==0 ) rc = SQLITE_NOMEM; + for(i=0; inArg && rc==SQLITE_OK; i++){ + char *zSql2 = sqlite3_mprintf(zInsertFmt[pAr->bZip], zTab, + pAr->bVerbose ? "shell_putsnl(name)" : "name", + pAr->azArg[i], pAr->zDir, zExists); + rc = arExecSql(pAr, zSql2); + sqlite3_free(zSql2); + } end_ar_transaction: - if( rc!=SQLITE_OK ){ - sqlite3_exec(pAr->db, "ROLLBACK TO ar; RELEASE ar;", 0, 0, 0); - }else{ - rc = arExecSql(pAr, "RELEASE ar;"); - if( pAr->bZip && pAr->zFile ){ - zSql = sqlite3_mprintf("DROP TABLE %s", zTemp); - arExecSql(pAr, zSql); - sqlite3_free(zSql); - } + if( rc!=SQLITE_OK ){ + sqlite3_exec(pAr->db, "ROLLBACK TO ar; RELEASE ar;", 0, 0, 0); + }else{ + rc = arExecSql(pAr, "RELEASE ar;"); + if( pAr->bZip && pAr->zFile ){ + zSql = sqlite3_mprintf("DROP TABLE %s", zTemp); + arExecSql(pAr, zSql); + sqlite3_free(zSql); } - sqlite3_free(zExists); - return rc; + } + sqlite3_free(zExists); + return rc; } /* ** Implementation of ".ar" dot command. */ static int arDotCommand( - ShellState *pState, /* Current shell tool state */ - int fromCmdLine, /* True if -A command-line option, not .ar cmd */ - char **azArg, /* Array of arguments passed to dot command */ - int nArg /* Number of entries in azArg[] */ + ShellState *pState, /* Current shell tool state */ + int fromCmdLine, /* True if -A command-line option, not .ar cmd */ + char **azArg, /* Array of arguments passed to dot command */ + int nArg /* Number of entries in azArg[] */ ){ - ArCommand cmd; - int rc; - memset(&cmd, 0, sizeof(cmd)); - cmd.fromCmdLine = fromCmdLine; - rc = arParseCommand(azArg, nArg, &cmd); - if( rc==SQLITE_OK ){ - int eDbType = SHELL_OPEN_UNSPEC; - cmd.p = pState; - cmd.db = pState->db; - if( cmd.zFile ){ - eDbType = deduceDatabaseType(cmd.zFile, 1); + ArCommand cmd; + int rc; + memset(&cmd, 0, sizeof(cmd)); + cmd.fromCmdLine = fromCmdLine; + rc = arParseCommand(azArg, nArg, &cmd); + if( rc==SQLITE_OK ){ + int eDbType = SHELL_OPEN_UNSPEC; + cmd.p = pState; + cmd.db = pState->db; + if( cmd.zFile ){ + eDbType = deduceDatabaseType(cmd.zFile, 1); + }else{ + eDbType = pState->openMode; + } + if( eDbType==SHELL_OPEN_ZIPFILE ){ + if( cmd.eCmd==AR_CMD_EXTRACT || cmd.eCmd==AR_CMD_LIST ){ + if( cmd.zFile==0 ){ + cmd.zSrcTable = sqlite3_mprintf("zip"); }else{ - eDbType = pState->openMode; - } - if( eDbType==SHELL_OPEN_ZIPFILE ){ - if( cmd.eCmd==AR_CMD_EXTRACT || cmd.eCmd==AR_CMD_LIST ){ - if( cmd.zFile==0 ){ - cmd.zSrcTable = sqlite3_mprintf("zip"); - }else{ - cmd.zSrcTable = sqlite3_mprintf("zipfile(%Q)", cmd.zFile); - } - } - cmd.bZip = 1; - }else if( cmd.zFile ){ - int flags; - if( cmd.bAppend ) eDbType = SHELL_OPEN_APPENDVFS; - if( cmd.eCmd==AR_CMD_CREATE || cmd.eCmd==AR_CMD_INSERT - || cmd.eCmd==AR_CMD_REMOVE || cmd.eCmd==AR_CMD_UPDATE ){ - flags = SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE; - }else{ - flags = SQLITE_OPEN_READONLY; - } - cmd.db = 0; - if( cmd.bDryRun ){ - utf8_printf(pState->out, "-- open database '%s'%s\n", cmd.zFile, - eDbType==SHELL_OPEN_APPENDVFS ? " using 'apndvfs'" : ""); - } - rc = sqlite3_open_v2(cmd.zFile, &cmd.db, flags, - eDbType==SHELL_OPEN_APPENDVFS ? "apndvfs" : 0); - if( rc!=SQLITE_OK ){ - utf8_printf(stderr, "cannot open file: %s (%s)\n", - cmd.zFile, sqlite3_errmsg(cmd.db) - ); - goto end_ar_command; - } - sqlite3_fileio_init(cmd.db, 0, 0); - sqlite3_sqlar_init(cmd.db, 0, 0); - sqlite3_create_function(cmd.db, "shell_putsnl", 1, SQLITE_UTF8, cmd.p, - shellPutsFunc, 0, 0); - - } - if( cmd.zSrcTable==0 && cmd.bZip==0 && cmd.eCmd!=AR_CMD_HELP ){ - if( cmd.eCmd!=AR_CMD_CREATE - && sqlite3_table_column_metadata(cmd.db,0,"sqlar","name",0,0,0,0,0) - ){ - utf8_printf(stderr, "database does not contain an 'sqlar' table\n"); - rc = SQLITE_ERROR; - goto end_ar_command; - } - cmd.zSrcTable = sqlite3_mprintf("sqlar"); - } + cmd.zSrcTable = sqlite3_mprintf("zipfile(%Q)", cmd.zFile); + } + } + cmd.bZip = 1; + }else if( cmd.zFile ){ + int flags; + if( cmd.bAppend ) eDbType = SHELL_OPEN_APPENDVFS; + if( cmd.eCmd==AR_CMD_CREATE || cmd.eCmd==AR_CMD_INSERT + || cmd.eCmd==AR_CMD_REMOVE || cmd.eCmd==AR_CMD_UPDATE ){ + flags = SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE; + }else{ + flags = SQLITE_OPEN_READONLY; + } + cmd.db = 0; + if( cmd.bDryRun ){ + utf8_printf(pState->out, "-- open database '%s'%s\n", cmd.zFile, + eDbType==SHELL_OPEN_APPENDVFS ? " using 'apndvfs'" : ""); + } + rc = sqlite3_open_v2(cmd.zFile, &cmd.db, flags, + eDbType==SHELL_OPEN_APPENDVFS ? "apndvfs" : 0); + if( rc!=SQLITE_OK ){ + utf8_printf(stderr, "cannot open file: %s (%s)\n", + cmd.zFile, sqlite3_errmsg(cmd.db) + ); + goto end_ar_command; + } + sqlite3_fileio_init(cmd.db, 0, 0); + sqlite3_sqlar_init(cmd.db, 0, 0); + sqlite3_create_function(cmd.db, "shell_putsnl", 1, SQLITE_UTF8, cmd.p, + shellPutsFunc, 0, 0); + + } + if( cmd.zSrcTable==0 && cmd.bZip==0 && cmd.eCmd!=AR_CMD_HELP ){ + if( cmd.eCmd!=AR_CMD_CREATE + && sqlite3_table_column_metadata(cmd.db,0,"sqlar","name",0,0,0,0,0) + ){ + utf8_printf(stderr, "database does not contain an 'sqlar' table\n"); + rc = SQLITE_ERROR; + goto end_ar_command; + } + cmd.zSrcTable = sqlite3_mprintf("sqlar"); + } - switch( cmd.eCmd ){ - case AR_CMD_CREATE: - rc = arCreateOrUpdateCommand(&cmd, 0, 0); - break; + switch( cmd.eCmd ){ + case AR_CMD_CREATE: + rc = arCreateOrUpdateCommand(&cmd, 0, 0); + break; - case AR_CMD_EXTRACT: - rc = arExtractCommand(&cmd); - break; + case AR_CMD_EXTRACT: + rc = arExtractCommand(&cmd); + break; - case AR_CMD_LIST: - rc = arListCommand(&cmd); - break; + case AR_CMD_LIST: + rc = arListCommand(&cmd); + break; - case AR_CMD_HELP: - arUsage(pState->out); - break; + case AR_CMD_HELP: + arUsage(pState->out); + break; - case AR_CMD_INSERT: - rc = arCreateOrUpdateCommand(&cmd, 1, 0); - break; + case AR_CMD_INSERT: + rc = arCreateOrUpdateCommand(&cmd, 1, 0); + break; - case AR_CMD_REMOVE: - rc = arRemoveCommand(&cmd); - break; + case AR_CMD_REMOVE: + rc = arRemoveCommand(&cmd); + break; - default: - assert( cmd.eCmd==AR_CMD_UPDATE ); - rc = arCreateOrUpdateCommand(&cmd, 1, 1); - break; - } + default: + assert( cmd.eCmd==AR_CMD_UPDATE ); + rc = arCreateOrUpdateCommand(&cmd, 1, 1); + break; } + } end_ar_command: - if( cmd.db!=pState->db ){ - close_db(cmd.db); - } - sqlite3_free(cmd.zSrcTable); + if( cmd.db!=pState->db ){ + close_db(cmd.db); + } + sqlite3_free(cmd.zSrcTable); - return rc; + return rc; } /* End of the ".archive" or ".ar" command logic *******************************************************************************/ @@ -17935,35 +17935,35 @@ end_ar_command: ** this function returns. */ static void shellExec(sqlite3 *db, int *pRc, const char *zSql){ - int rc = *pRc; - if( rc==SQLITE_OK ){ - char *zErr = 0; - rc = sqlite3_exec(db, zSql, 0, 0, &zErr); - if( rc!=SQLITE_OK ){ - raw_printf(stderr, "SQL error: %s\n", zErr); - } - sqlite3_free(zErr); - *pRc = rc; + int rc = *pRc; + if( rc==SQLITE_OK ){ + char *zErr = 0; + rc = sqlite3_exec(db, zSql, 0, 0, &zErr); + if( rc!=SQLITE_OK ){ + raw_printf(stderr, "SQL error: %s\n", zErr); } + sqlite3_free(zErr); + *pRc = rc; + } } /* ** Like shellExec(), except that zFmt is a printf() style format string. */ static void shellExecPrintf(sqlite3 *db, int *pRc, const char *zFmt, ...){ - char *z = 0; - if( *pRc==SQLITE_OK ){ - va_list ap; - va_start(ap, zFmt); - z = sqlite3_vmprintf(zFmt, ap); - va_end(ap); - if( z==0 ){ - *pRc = SQLITE_NOMEM; - }else{ - shellExec(db, pRc, z); - } - sqlite3_free(z); + char *z = 0; + if( *pRc==SQLITE_OK ){ + va_list ap; + va_start(ap, zFmt); + z = sqlite3_vmprintf(zFmt, ap); + va_end(ap); + if( z==0 ){ + *pRc = SQLITE_NOMEM; + }else{ + shellExec(db, pRc, z); } + sqlite3_free(z); + } } /* @@ -17973,41 +17973,41 @@ static void shellExecPrintf(sqlite3 *db, int *pRc, const char *zFmt, ...){ ** to SQLITE_NOMEM and NULL returned. */ static void *shellMalloc(int *pRc, sqlite3_int64 nByte){ - void *pRet = 0; - if( *pRc==SQLITE_OK ){ - pRet = sqlite3_malloc64(nByte); - if( pRet==0 ){ - *pRc = SQLITE_NOMEM; - }else{ - memset(pRet, 0, nByte); - } + void *pRet = 0; + if( *pRc==SQLITE_OK ){ + pRet = sqlite3_malloc64(nByte); + if( pRet==0 ){ + *pRc = SQLITE_NOMEM; + }else{ + memset(pRet, 0, nByte); } - return pRet; + } + return pRet; } /* ** If *pRc is not SQLITE_OK when this function is called, it is a no-op. ** Otherwise, zFmt is treated as a printf() style string. The result of -** formatting it along with any trailing arguments is written into a +** formatting it along with any trailing arguments is written into a ** buffer obtained from sqlite3_malloc(), and pointer to which is returned. ** It is the responsibility of the caller to eventually free this buffer ** using a call to sqlite3_free(). -** -** If an OOM error occurs, (*pRc) is set to SQLITE_NOMEM and a NULL +** +** If an OOM error occurs, (*pRc) is set to SQLITE_NOMEM and a NULL ** pointer returned. */ static char *shellMPrintf(int *pRc, const char *zFmt, ...){ - char *z = 0; - if( *pRc==SQLITE_OK ){ - va_list ap; - va_start(ap, zFmt); - z = sqlite3_vmprintf(zFmt, ap); - va_end(ap); - if( z==0 ){ - *pRc = SQLITE_NOMEM; - } + char *z = 0; + if( *pRc==SQLITE_OK ){ + va_list ap; + va_start(ap, zFmt); + z = sqlite3_vmprintf(zFmt, ap); + va_end(ap); + if( z==0 ){ + *pRc = SQLITE_NOMEM; } - return z; + } + return z; } /* @@ -18017,10 +18017,10 @@ static char *shellMPrintf(int *pRc, const char *zFmt, ...){ */ typedef struct RecoverTable RecoverTable; struct RecoverTable { - char *zQuoted; /* Quoted version of table name */ - int nCol; /* Number of columns in table */ - char **azlCol; /* Array of column lists */ - int iPk; /* Index of IPK column */ + char *zQuoted; /* Quoted version of table name */ + int nCol; /* Number of columns in table */ + char **azlCol; /* Array of column lists */ + int iPk; /* Index of IPK column */ }; /* @@ -18028,17 +18028,17 @@ struct RecoverTable { ** recoverOrphanTable(). */ static void recoverFreeTable(RecoverTable *pTab){ - if( pTab ){ - sqlite3_free(pTab->zQuoted); - if( pTab->azlCol ){ - int i; - for(i=0; i<=pTab->nCol; i++){ - sqlite3_free(pTab->azlCol[i]); - } - sqlite3_free(pTab->azlCol); - } - sqlite3_free(pTab); + if( pTab ){ + sqlite3_free(pTab->zQuoted); + if( pTab->azlCol ){ + int i; + for(i=0; i<=pTab->nCol; i++){ + sqlite3_free(pTab->azlCol[i]); + } + sqlite3_free(pTab->azlCol); } + sqlite3_free(pTab); + } } /* @@ -18049,120 +18049,120 @@ static void recoverFreeTable(RecoverTable *pTab){ ** recoverFreeTable(). */ static RecoverTable *recoverNewTable( - int *pRc, /* IN/OUT: Error code */ - const char *zName, /* Name of table */ - const char *zSql, /* CREATE TABLE statement */ - int bIntkey, - int nCol + int *pRc, /* IN/OUT: Error code */ + const char *zName, /* Name of table */ + const char *zSql, /* CREATE TABLE statement */ + int bIntkey, + int nCol ){ - sqlite3 *dbtmp = 0; /* sqlite3 handle for testing CREATE TABLE */ - int rc = *pRc; - RecoverTable *pTab = 0; - - pTab = (RecoverTable*)shellMalloc(&rc, sizeof(RecoverTable)); + sqlite3 *dbtmp = 0; /* sqlite3 handle for testing CREATE TABLE */ + int rc = *pRc; + RecoverTable *pTab = 0; + + pTab = (RecoverTable*)shellMalloc(&rc, sizeof(RecoverTable)); + if( rc==SQLITE_OK ){ + int nSqlCol = 0; + int bSqlIntkey = 0; + sqlite3_stmt *pStmt = 0; + + rc = sqlite3_open("", &dbtmp); if( rc==SQLITE_OK ){ - int nSqlCol = 0; - int bSqlIntkey = 0; - sqlite3_stmt *pStmt = 0; - - rc = sqlite3_open("", &dbtmp); - if( rc==SQLITE_OK ){ - sqlite3_create_function(dbtmp, "shell_idquote", 1, SQLITE_UTF8, 0, - shellIdQuote, 0, 0); - } - if( rc==SQLITE_OK ){ - rc = sqlite3_exec(dbtmp, "PRAGMA writable_schema = on", 0, 0, 0); - } - if( rc==SQLITE_OK ){ - rc = sqlite3_exec(dbtmp, zSql, 0, 0, 0); - if( rc==SQLITE_ERROR ){ - rc = SQLITE_OK; - goto finished; - } - } - shellPreparePrintf(dbtmp, &rc, &pStmt, - "SELECT count(*) FROM pragma_table_info(%Q)", zName - ); - if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){ - nSqlCol = sqlite3_column_int(pStmt, 0); - } - shellFinalize(&rc, pStmt); + sqlite3_create_function(dbtmp, "shell_idquote", 1, SQLITE_UTF8, 0, + shellIdQuote, 0, 0); + } + if( rc==SQLITE_OK ){ + rc = sqlite3_exec(dbtmp, "PRAGMA writable_schema = on", 0, 0, 0); + } + if( rc==SQLITE_OK ){ + rc = sqlite3_exec(dbtmp, zSql, 0, 0, 0); + if( rc==SQLITE_ERROR ){ + rc = SQLITE_OK; + goto finished; + } + } + shellPreparePrintf(dbtmp, &rc, &pStmt, + "SELECT count(*) FROM pragma_table_info(%Q)", zName + ); + if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){ + nSqlCol = sqlite3_column_int(pStmt, 0); + } + shellFinalize(&rc, pStmt); - if( rc!=SQLITE_OK || nSqlColiPk to the index ** of the column, where columns are 0-numbered from left to right. ** Or, if this is a WITHOUT ROWID table or if there is no IPK column, ** leave zPk as "_rowid_" and pTab->iPk at -2. */ - pTab->iPk = -2; - if( bIntkey ){ - shellPreparePrintf(dbtmp, &rc, &pPkFinder, - "SELECT cid, name FROM pragma_table_info(%Q) " - " WHERE pk=1 AND type='integer' COLLATE nocase" - " AND NOT EXISTS (SELECT cid FROM pragma_table_info(%Q) WHERE pk=2)" - , zName, zName - ); - if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pPkFinder) ){ - pTab->iPk = sqlite3_column_int(pPkFinder, 0); - zPk = (const char*)sqlite3_column_text(pPkFinder, 1); - } - } - - pTab->zQuoted = shellMPrintf(&rc, "\"%w\"", zName); - pTab->azlCol = (char**)shellMalloc(&rc, sizeof(char*) * (nSqlCol+1)); - pTab->nCol = nSqlCol; - - if( bIntkey ){ - pTab->azlCol[0] = shellMPrintf(&rc, "\"%w\"", zPk); - }else{ - pTab->azlCol[0] = shellMPrintf(&rc, ""); - } - i = 1; - shellPreparePrintf(dbtmp, &rc, &pStmt, - "SELECT %Q || group_concat(shell_idquote(name), ', ') " - " FILTER (WHERE cid!=%d) OVER (ORDER BY %s cid) " - "FROM pragma_table_info(%Q)", - bIntkey ? ", " : "", pTab->iPk, - bIntkey ? "" : "(CASE WHEN pk=0 THEN 1000000 ELSE pk END), ", - zName - ); - while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){ - const char *zText = (const char*)sqlite3_column_text(pStmt, 0); - pTab->azlCol[i] = shellMPrintf(&rc, "%s%s", pTab->azlCol[0], zText); - i++; - } - shellFinalize(&rc, pStmt); + pTab->iPk = -2; + if( bIntkey ){ + shellPreparePrintf(dbtmp, &rc, &pPkFinder, + "SELECT cid, name FROM pragma_table_info(%Q) " + " WHERE pk=1 AND type='integer' COLLATE nocase" + " AND NOT EXISTS (SELECT cid FROM pragma_table_info(%Q) WHERE pk=2)" + , zName, zName + ); + if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pPkFinder) ){ + pTab->iPk = sqlite3_column_int(pPkFinder, 0); + zPk = (const char*)sqlite3_column_text(pPkFinder, 1); + } + } + + pTab->zQuoted = shellMPrintf(&rc, "\"%w\"", zName); + pTab->azlCol = (char**)shellMalloc(&rc, sizeof(char*) * (nSqlCol+1)); + pTab->nCol = nSqlCol; + + if( bIntkey ){ + pTab->azlCol[0] = shellMPrintf(&rc, "\"%w\"", zPk); + }else{ + pTab->azlCol[0] = shellMPrintf(&rc, ""); + } + i = 1; + shellPreparePrintf(dbtmp, &rc, &pStmt, + "SELECT %Q || group_concat(shell_idquote(name), ', ') " + " FILTER (WHERE cid!=%d) OVER (ORDER BY %s cid) " + "FROM pragma_table_info(%Q)", + bIntkey ? ", " : "", pTab->iPk, + bIntkey ? "" : "(CASE WHEN pk=0 THEN 1000000 ELSE pk END), ", + zName + ); + while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){ + const char *zText = (const char*)sqlite3_column_text(pStmt, 0); + pTab->azlCol[i] = shellMPrintf(&rc, "%s%s", pTab->azlCol[0], zText); + i++; + } + shellFinalize(&rc, pStmt); - shellFinalize(&rc, pPkFinder); - } + shellFinalize(&rc, pPkFinder); } + } -finished: - sqlite3_close(dbtmp); - *pRc = rc; - if( rc!=SQLITE_OK || (pTab && pTab->zQuoted==0) ){ - recoverFreeTable(pTab); - pTab = 0; - } - return pTab; + finished: + sqlite3_close(dbtmp); + *pRc = rc; + if( rc!=SQLITE_OK || (pTab && pTab->zQuoted==0) ){ + recoverFreeTable(pTab); + pTab = 0; + } + return pTab; } /* @@ -18174,113 +18174,113 @@ finished: ** those. ** ** If a table is found, a (RecoverTable*) object is returned. Or, if -** no such table is found, but bIntkey is false and iRoot is the +** no such table is found, but bIntkey is false and iRoot is the ** root page of an index in the recovered schema, then (*pbNoop) is ** set to true and NULL returned. Or, if there is no such table or ** index, NULL is returned and (*pbNoop) set to 0, indicating that ** the caller should write data to the orphans table. */ static RecoverTable *recoverFindTable( - ShellState *pState, /* Shell state object */ - int *pRc, /* IN/OUT: Error code */ - int iRoot, /* Root page of table */ - int bIntkey, /* True for an intkey table */ - int nCol, /* Number of columns in table */ - int *pbNoop /* OUT: True if iRoot is root of index */ + ShellState *pState, /* Shell state object */ + int *pRc, /* IN/OUT: Error code */ + int iRoot, /* Root page of table */ + int bIntkey, /* True for an intkey table */ + int nCol, /* Number of columns in table */ + int *pbNoop /* OUT: True if iRoot is root of index */ ){ - sqlite3_stmt *pStmt = 0; - RecoverTable *pRet = 0; - int bNoop = 0; - const char *zSql = 0; - const char *zName = 0; + sqlite3_stmt *pStmt = 0; + RecoverTable *pRet = 0; + int bNoop = 0; + const char *zSql = 0; + const char *zName = 0; - /* Search the recovered schema for an object with root page iRoot. */ - shellPreparePrintf(pState->db, pRc, &pStmt, - "SELECT type, name, sql FROM recovery.schema WHERE rootpage=%d", iRoot - ); - while( *pRc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){ - const char *zType = (const char*)sqlite3_column_text(pStmt, 0); - if( bIntkey==0 && sqlite3_stricmp(zType, "index")==0 ){ - bNoop = 1; - break; - } - if( sqlite3_stricmp(zType, "table")==0 ){ - zName = (const char*)sqlite3_column_text(pStmt, 1); - zSql = (const char*)sqlite3_column_text(pStmt, 2); - pRet = recoverNewTable(pRc, zName, zSql, bIntkey, nCol); - break; - } + /* Search the recovered schema for an object with root page iRoot. */ + shellPreparePrintf(pState->db, pRc, &pStmt, + "SELECT type, name, sql FROM recovery.schema WHERE rootpage=%d", iRoot + ); + while( *pRc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){ + const char *zType = (const char*)sqlite3_column_text(pStmt, 0); + if( bIntkey==0 && sqlite3_stricmp(zType, "index")==0 ){ + bNoop = 1; + break; + } + if( sqlite3_stricmp(zType, "table")==0 ){ + zName = (const char*)sqlite3_column_text(pStmt, 1); + zSql = (const char*)sqlite3_column_text(pStmt, 2); + pRet = recoverNewTable(pRc, zName, zSql, bIntkey, nCol); + break; } + } - shellFinalize(pRc, pStmt); - *pbNoop = bNoop; - return pRet; + shellFinalize(pRc, pStmt); + *pbNoop = bNoop; + return pRet; } /* ** Return a RecoverTable object representing the orphans table. */ static RecoverTable *recoverOrphanTable( - ShellState *pState, /* Shell state object */ - int *pRc, /* IN/OUT: Error code */ - const char *zLostAndFound, /* Base name for orphans table */ - int nCol /* Number of user data columns */ + ShellState *pState, /* Shell state object */ + int *pRc, /* IN/OUT: Error code */ + const char *zLostAndFound, /* Base name for orphans table */ + int nCol /* Number of user data columns */ ){ - RecoverTable *pTab = 0; - if( nCol>=0 && *pRc==SQLITE_OK ){ - int i; + RecoverTable *pTab = 0; + if( nCol>=0 && *pRc==SQLITE_OK ){ + int i; - /* This block determines the name of the orphan table. The prefered + /* This block determines the name of the orphan table. The prefered ** name is zLostAndFound. But if that clashes with another name ** in the recovered schema, try zLostAndFound_0, zLostAndFound_1 ** and so on until a non-clashing name is found. */ - int iTab = 0; - char *zTab = shellMPrintf(pRc, "%s", zLostAndFound); - sqlite3_stmt *pTest = 0; - shellPrepare(pState->db, pRc, - "SELECT 1 FROM recovery.schema WHERE name=?", &pTest - ); - if( pTest ) sqlite3_bind_text(pTest, 1, zTab, -1, SQLITE_TRANSIENT); - while( *pRc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pTest) ){ - shellReset(pRc, pTest); - sqlite3_free(zTab); - zTab = shellMPrintf(pRc, "%s_%d", zLostAndFound, iTab++); - sqlite3_bind_text(pTest, 1, zTab, -1, SQLITE_TRANSIENT); + int iTab = 0; + char *zTab = shellMPrintf(pRc, "%s", zLostAndFound); + sqlite3_stmt *pTest = 0; + shellPrepare(pState->db, pRc, + "SELECT 1 FROM recovery.schema WHERE name=?", &pTest + ); + if( pTest ) sqlite3_bind_text(pTest, 1, zTab, -1, SQLITE_TRANSIENT); + while( *pRc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pTest) ){ + shellReset(pRc, pTest); + sqlite3_free(zTab); + zTab = shellMPrintf(pRc, "%s_%d", zLostAndFound, iTab++); + sqlite3_bind_text(pTest, 1, zTab, -1, SQLITE_TRANSIENT); + } + shellFinalize(pRc, pTest); + + pTab = (RecoverTable*)shellMalloc(pRc, sizeof(RecoverTable)); + if( pTab ){ + pTab->zQuoted = shellMPrintf(pRc, "\"%w\"", zTab); + pTab->nCol = nCol; + pTab->iPk = -2; + if( nCol>0 ){ + pTab->azlCol = (char**)shellMalloc(pRc, sizeof(char*) * (nCol+1)); + if( pTab->azlCol ){ + pTab->azlCol[nCol] = shellMPrintf(pRc, ""); + for(i=nCol-1; i>=0; i--){ + pTab->azlCol[i] = shellMPrintf(pRc, "%s, NULL", pTab->azlCol[i+1]); + } } - shellFinalize(pRc, pTest); - - pTab = (RecoverTable*)shellMalloc(pRc, sizeof(RecoverTable)); - if( pTab ){ - pTab->zQuoted = shellMPrintf(pRc, "\"%w\"", zTab); - pTab->nCol = nCol; - pTab->iPk = -2; - if( nCol>0 ){ - pTab->azlCol = (char**)shellMalloc(pRc, sizeof(char*) * (nCol+1)); - if( pTab->azlCol ){ - pTab->azlCol[nCol] = shellMPrintf(pRc, ""); - for(i=nCol-1; i>=0; i--){ - pTab->azlCol[i] = shellMPrintf(pRc, "%s, NULL", pTab->azlCol[i+1]); - } - } - } + } - if( *pRc!=SQLITE_OK ){ - recoverFreeTable(pTab); - pTab = 0; - }else{ - raw_printf(pState->out, - "CREATE TABLE %s(rootpgno INTEGER, " - "pgno INTEGER, nfield INTEGER, id INTEGER", pTab->zQuoted - ); - for(i=0; iout, ", c%d", i); - } - raw_printf(pState->out, ");\n"); - } + if( *pRc!=SQLITE_OK ){ + recoverFreeTable(pTab); + pTab = 0; + }else{ + raw_printf(pState->out, + "CREATE TABLE %s(rootpgno INTEGER, " + "pgno INTEGER, nfield INTEGER, id INTEGER", pTab->zQuoted + ); + for(i=0; iout, ", c%d", i); } - sqlite3_free(zTab); + raw_printf(pState->out, ");\n"); + } } - return pTab; + sqlite3_free(zTab); + } + return pTab; } /* @@ -18289,317 +18289,317 @@ static RecoverTable *recoverOrphanTable( ** on stream pState->out. */ static int recoverDatabaseCmd(ShellState *pState, int nArg, char **azArg){ - int rc = SQLITE_OK; - sqlite3_stmt *pLoop = 0; /* Loop through all root pages */ - sqlite3_stmt *pPages = 0; /* Loop through all pages in a group */ - sqlite3_stmt *pCells = 0; /* Loop through all cells in a page */ - const char *zRecoveryDb = ""; /* Name of "recovery" database */ - const char *zLostAndFound = "lost_and_found"; - int i; - int nOrphan = -1; - RecoverTable *pOrphan = 0; - - int bFreelist = 1; /* 0 if --freelist-corrupt is specified */ - int bRowids = 1; /* 0 if --no-rowids */ - for(i=1; iout, azArg[0]); - return 1; - } + int rc = SQLITE_OK; + sqlite3_stmt *pLoop = 0; /* Loop through all root pages */ + sqlite3_stmt *pPages = 0; /* Loop through all pages in a group */ + sqlite3_stmt *pCells = 0; /* Loop through all cells in a page */ + const char *zRecoveryDb = ""; /* Name of "recovery" database */ + const char *zLostAndFound = "lost_and_found"; + int i; + int nOrphan = -1; + RecoverTable *pOrphan = 0; + + int bFreelist = 1; /* 0 if --freelist-corrupt is specified */ + int bRowids = 1; /* 0 if --no-rowids */ + for(i=1; idb, &rc, - /* Attach an in-memory database named 'recovery'. Create an indexed - ** cache of the sqlite_dbptr virtual table. */ - "PRAGMA writable_schema = on;" - "ATTACH %Q AS recovery;" - "DROP TABLE IF EXISTS recovery.dbptr;" - "DROP TABLE IF EXISTS recovery.freelist;" - "DROP TABLE IF EXISTS recovery.map;" - "DROP TABLE IF EXISTS recovery.schema;" - "CREATE TABLE recovery.freelist(pgno INTEGER PRIMARY KEY);", zRecoveryDb - ); - - if( bFreelist ){ - shellExec(pState->db, &rc, - "WITH trunk(pgno) AS (" - " SELECT shell_int32(" - " (SELECT data FROM sqlite_dbpage WHERE pgno=1), 8) AS x " - " WHERE x>0" - " UNION" - " SELECT shell_int32(" - " (SELECT data FROM sqlite_dbpage WHERE pgno=trunk.pgno), 0) AS x " - " FROM trunk WHERE x>0" - ")," - "freelist(data, n, freepgno) AS (" - " SELECT data, min(16384, shell_int32(data, 1)-1), t.pgno " - " FROM trunk t, sqlite_dbpage s WHERE s.pgno=t.pgno" - " UNION ALL" - " SELECT data, n-1, shell_int32(data, 2+n) " - " FROM freelist WHERE n>=0" - ")" - "REPLACE INTO recovery.freelist SELECT freepgno FROM freelist;" - ); + else{ + utf8_printf(stderr, "unexpected option: %s\n", azArg[i]); + showHelp(pState->out, azArg[0]); + return 1; } + } - /* If this is an auto-vacuum database, add all pointer-map pages to - ** the freelist table. Do this regardless of whether or not - ** --freelist-corrupt was specified. */ + shellExecPrintf(pState->db, &rc, + /* Attach an in-memory database named 'recovery'. Create an indexed + ** cache of the sqlite_dbptr virtual table. */ + "PRAGMA writable_schema = on;" + "ATTACH %Q AS recovery;" + "DROP TABLE IF EXISTS recovery.dbptr;" + "DROP TABLE IF EXISTS recovery.freelist;" + "DROP TABLE IF EXISTS recovery.map;" + "DROP TABLE IF EXISTS recovery.schema;" + "CREATE TABLE recovery.freelist(pgno INTEGER PRIMARY KEY);", zRecoveryDb + ); + + if( bFreelist ){ shellExec(pState->db, &rc, - "WITH ptrmap(pgno) AS (" - " SELECT 2 WHERE shell_int32(" - " (SELECT data FROM sqlite_dbpage WHERE pgno=1), 13" - " )" - " UNION ALL " - " SELECT pgno+1+(SELECT page_size FROM pragma_page_size)/5 AS pp " - " FROM ptrmap WHERE pp<=(SELECT page_count FROM pragma_page_count)" - ")" - "REPLACE INTO recovery.freelist SELECT pgno FROM ptrmap" + "WITH trunk(pgno) AS (" + " SELECT shell_int32(" + " (SELECT data FROM sqlite_dbpage WHERE pgno=1), 8) AS x " + " WHERE x>0" + " UNION" + " SELECT shell_int32(" + " (SELECT data FROM sqlite_dbpage WHERE pgno=trunk.pgno), 0) AS x " + " FROM trunk WHERE x>0" + ")," + "freelist(data, n, freepgno) AS (" + " SELECT data, min(16384, shell_int32(data, 1)-1), t.pgno " + " FROM trunk t, sqlite_dbpage s WHERE s.pgno=t.pgno" + " UNION ALL" + " SELECT data, n-1, shell_int32(data, 2+n) " + " FROM freelist WHERE n>=0" + ")" + "REPLACE INTO recovery.freelist SELECT freepgno FROM freelist;" ); + } - shellExec(pState->db, &rc, - "CREATE TABLE recovery.dbptr(" - " pgno, child, PRIMARY KEY(child, pgno)" - ") WITHOUT ROWID;" - "INSERT OR IGNORE INTO recovery.dbptr(pgno, child) " - " SELECT * FROM sqlite_dbptr" - " WHERE pgno NOT IN freelist AND child NOT IN freelist;" - - /* Delete any pointer to page 1. This ensures that page 1 is considered + /* If this is an auto-vacuum database, add all pointer-map pages to + ** the freelist table. Do this regardless of whether or not + ** --freelist-corrupt was specified. */ + shellExec(pState->db, &rc, + "WITH ptrmap(pgno) AS (" + " SELECT 2 WHERE shell_int32(" + " (SELECT data FROM sqlite_dbpage WHERE pgno=1), 13" + " )" + " UNION ALL " + " SELECT pgno+1+(SELECT page_size FROM pragma_page_size)/5 AS pp " + " FROM ptrmap WHERE pp<=(SELECT page_count FROM pragma_page_count)" + ")" + "REPLACE INTO recovery.freelist SELECT pgno FROM ptrmap" + ); + + shellExec(pState->db, &rc, + "CREATE TABLE recovery.dbptr(" + " pgno, child, PRIMARY KEY(child, pgno)" + ") WITHOUT ROWID;" + "INSERT OR IGNORE INTO recovery.dbptr(pgno, child) " + " SELECT * FROM sqlite_dbptr" + " WHERE pgno NOT IN freelist AND child NOT IN freelist;" + + /* Delete any pointer to page 1. This ensures that page 1 is considered ** a root page, regardless of how corrupt the db is. */ - "DELETE FROM recovery.dbptr WHERE child = 1;" + "DELETE FROM recovery.dbptr WHERE child = 1;" - /* Delete all pointers to any pages that have more than one pointer + /* Delete all pointers to any pages that have more than one pointer ** to them. Such pages will be treated as root pages when recovering ** data. */ - "DELETE FROM recovery.dbptr WHERE child IN (" - " SELECT child FROM recovery.dbptr GROUP BY child HAVING count(*)>1" - ");" + "DELETE FROM recovery.dbptr WHERE child IN (" + " SELECT child FROM recovery.dbptr GROUP BY child HAVING count(*)>1" + ");" - /* Create the "map" table that will (eventually) contain instructions - ** for dealing with each page in the db that contains one or more + /* Create the "map" table that will (eventually) contain instructions + ** for dealing with each page in the db that contains one or more ** records. */ - "CREATE TABLE recovery.map(" - "pgno INTEGER PRIMARY KEY, maxlen INT, intkey, root INT" - ");" + "CREATE TABLE recovery.map(" + "pgno INTEGER PRIMARY KEY, maxlen INT, intkey, root INT" + ");" - /* Populate table [map]. If there are circular loops of pages in the + /* Populate table [map]. If there are circular loops of pages in the ** database, the following adds all pages in such a loop to the map ** as individual root pages. This could be handled better. */ - "WITH pages(i, maxlen) AS (" - " SELECT page_count, (" - " SELECT max(field+1) FROM sqlite_dbdata WHERE pgno=page_count" - " ) FROM pragma_page_count WHERE page_count>0" - " UNION ALL" - " SELECT i-1, (" - " SELECT max(field+1) FROM sqlite_dbdata WHERE pgno=i-1" - " ) FROM pages WHERE i>=2" - ")" - "INSERT INTO recovery.map(pgno, maxlen, intkey, root) " - " SELECT i, maxlen, NULL, (" - " WITH p(orig, pgno, parent) AS (" - " SELECT 0, i, (SELECT pgno FROM recovery.dbptr WHERE child=i)" - " UNION " - " SELECT i, p.parent, " - " (SELECT pgno FROM recovery.dbptr WHERE child=p.parent) FROM p" - " )" - " SELECT pgno FROM p WHERE (parent IS NULL OR pgno = orig)" - ") " - "FROM pages WHERE maxlen IS NOT NULL AND i NOT IN freelist;" - "UPDATE recovery.map AS o SET intkey = (" - " SELECT substr(data, 1, 1)==X'0D' FROM sqlite_dbpage WHERE pgno=o.pgno" - ");" - - /* Extract data from page 1 and any linked pages into table + "WITH pages(i, maxlen) AS (" + " SELECT page_count, (" + " SELECT max(field+1) FROM sqlite_dbdata WHERE pgno=page_count" + " ) FROM pragma_page_count WHERE page_count>0" + " UNION ALL" + " SELECT i-1, (" + " SELECT max(field+1) FROM sqlite_dbdata WHERE pgno=i-1" + " ) FROM pages WHERE i>=2" + ")" + "INSERT INTO recovery.map(pgno, maxlen, intkey, root) " + " SELECT i, maxlen, NULL, (" + " WITH p(orig, pgno, parent) AS (" + " SELECT 0, i, (SELECT pgno FROM recovery.dbptr WHERE child=i)" + " UNION " + " SELECT i, p.parent, " + " (SELECT pgno FROM recovery.dbptr WHERE child=p.parent) FROM p" + " )" + " SELECT pgno FROM p WHERE (parent IS NULL OR pgno = orig)" + ") " + "FROM pages WHERE maxlen IS NOT NULL AND i NOT IN freelist;" + "UPDATE recovery.map AS o SET intkey = (" + " SELECT substr(data, 1, 1)==X'0D' FROM sqlite_dbpage WHERE pgno=o.pgno" + ");" + + /* Extract data from page 1 and any linked pages into table ** recovery.schema. With the same schema as an sqlite_schema table. */ - "CREATE TABLE recovery.schema(type, name, tbl_name, rootpage, sql);" - "INSERT INTO recovery.schema SELECT " - " max(CASE WHEN field=0 THEN value ELSE NULL END)," - " max(CASE WHEN field=1 THEN value ELSE NULL END)," - " max(CASE WHEN field=2 THEN value ELSE NULL END)," - " max(CASE WHEN field=3 THEN value ELSE NULL END)," - " max(CASE WHEN field=4 THEN value ELSE NULL END)" - "FROM sqlite_dbdata WHERE pgno IN (" - " SELECT pgno FROM recovery.map WHERE root=1" - ")" - "GROUP BY pgno, cell;" - "CREATE INDEX recovery.schema_rootpage ON schema(rootpage);" - ); - - /* Open a transaction, then print out all non-virtual, non-"sqlite_%" + "CREATE TABLE recovery.schema(type, name, tbl_name, rootpage, sql);" + "INSERT INTO recovery.schema SELECT " + " max(CASE WHEN field=0 THEN value ELSE NULL END)," + " max(CASE WHEN field=1 THEN value ELSE NULL END)," + " max(CASE WHEN field=2 THEN value ELSE NULL END)," + " max(CASE WHEN field=3 THEN value ELSE NULL END)," + " max(CASE WHEN field=4 THEN value ELSE NULL END)" + "FROM sqlite_dbdata WHERE pgno IN (" + " SELECT pgno FROM recovery.map WHERE root=1" + ")" + "GROUP BY pgno, cell;" + "CREATE INDEX recovery.schema_rootpage ON schema(rootpage);" + ); + + /* Open a transaction, then print out all non-virtual, non-"sqlite_%" ** CREATE TABLE statements that extracted from the existing schema. */ - if( rc==SQLITE_OK ){ - sqlite3_stmt *pStmt = 0; - /* ".recover" might output content in an order which causes immediate + if( rc==SQLITE_OK ){ + sqlite3_stmt *pStmt = 0; + /* ".recover" might output content in an order which causes immediate ** foreign key constraints to be violated. So disable foreign-key ** constraint enforcement to prevent problems when running the output ** script. */ - raw_printf(pState->out, "PRAGMA foreign_keys=OFF;\n"); - raw_printf(pState->out, "BEGIN;\n"); - raw_printf(pState->out, "PRAGMA writable_schema = on;\n"); - shellPrepare(pState->db, &rc, - "SELECT sql FROM recovery.schema " - "WHERE type='table' AND sql LIKE 'create table%'", &pStmt - ); - while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){ - const char *zCreateTable = (const char*)sqlite3_column_text(pStmt, 0); - raw_printf(pState->out, "CREATE TABLE IF NOT EXISTS %s;\n", - &zCreateTable[12] - ); - } - shellFinalize(&rc, pStmt); - } - - /* Figure out if an orphan table will be required. And if so, how many - ** user columns it should contain */ + raw_printf(pState->out, "PRAGMA foreign_keys=OFF;\n"); + raw_printf(pState->out, "BEGIN;\n"); + raw_printf(pState->out, "PRAGMA writable_schema = on;\n"); shellPrepare(pState->db, &rc, - "SELECT coalesce(max(maxlen), -2) FROM recovery.map WHERE root>1" - , &pLoop + "SELECT sql FROM recovery.schema " + "WHERE type='table' AND sql LIKE 'create table%'", &pStmt ); - if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pLoop) ){ - nOrphan = sqlite3_column_int(pLoop, 0); + while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){ + const char *zCreateTable = (const char*)sqlite3_column_text(pStmt, 0); + raw_printf(pState->out, "CREATE TABLE IF NOT EXISTS %s;\n", + &zCreateTable[12] + ); } - shellFinalize(&rc, pLoop); - pLoop = 0; - - shellPrepare(pState->db, &rc, - "SELECT pgno FROM recovery.map WHERE root=?", &pPages - ); - - shellPrepare(pState->db, &rc, - "SELECT max(field), group_concat(shell_escape_crnl(quote" - "(case when (? AND field<0) then NULL else value end)" - "), ', ')" - ", min(field) " - "FROM sqlite_dbdata WHERE pgno = ? AND field != ?" - "GROUP BY cell", &pCells - ); - - /* Loop through each root page. */ - shellPrepare(pState->db, &rc, - "SELECT root, intkey, max(maxlen) FROM recovery.map" - " WHERE root>1 GROUP BY root, intkey ORDER BY root=(" - " SELECT rootpage FROM recovery.schema WHERE name='sqlite_sequence'" - ")", &pLoop - ); - while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pLoop) ){ - int iRoot = sqlite3_column_int(pLoop, 0); - int bIntkey = sqlite3_column_int(pLoop, 1); - int nCol = sqlite3_column_int(pLoop, 2); - int bNoop = 0; - RecoverTable *pTab; - - assert( bIntkey==0 || bIntkey==1 ); - pTab = recoverFindTable(pState, &rc, iRoot, bIntkey, nCol, &bNoop); - if( bNoop || rc ) continue; - if( pTab==0 ){ - if( pOrphan==0 ){ - pOrphan = recoverOrphanTable(pState, &rc, zLostAndFound, nOrphan); - } - pTab = pOrphan; - if( pTab==0 ) break; - } - - if( 0==sqlite3_stricmp(pTab->zQuoted, "\"sqlite_sequence\"") ){ - raw_printf(pState->out, "DELETE FROM sqlite_sequence;\n"); - } - sqlite3_bind_int(pPages, 1, iRoot); - if( bRowids==0 && pTab->iPk<0 ){ - sqlite3_bind_int(pCells, 1, 1); - }else{ - sqlite3_bind_int(pCells, 1, 0); - } - sqlite3_bind_int(pCells, 3, pTab->iPk); - - while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pPages) ){ - int iPgno = sqlite3_column_int(pPages, 0); - sqlite3_bind_int(pCells, 2, iPgno); - while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pCells) ){ - int nField = sqlite3_column_int(pCells, 0); - int iMin = sqlite3_column_int(pCells, 2); - const char *zVal = (const char*)sqlite3_column_text(pCells, 1); - - RecoverTable *pTab2 = pTab; - if( pTab!=pOrphan && (iMin<0)!=bIntkey ){ - if( pOrphan==0 ){ - pOrphan = recoverOrphanTable(pState, &rc, zLostAndFound, nOrphan); - } - pTab2 = pOrphan; - if( pTab2==0 ) break; - } + shellFinalize(&rc, pStmt); + } - nField = nField+1; - if( pTab2==pOrphan ){ - raw_printf(pState->out, - "INSERT INTO %s VALUES(%d, %d, %d, %s%s%s);\n", - pTab2->zQuoted, iRoot, iPgno, nField, - iMin<0 ? "" : "NULL, ", zVal, pTab2->azlCol[nField] - ); - }else{ - raw_printf(pState->out, "INSERT INTO %s(%s) VALUES( %s );\n", - pTab2->zQuoted, pTab2->azlCol[nField], zVal - ); - } - } - shellReset(&rc, pCells); - } - shellReset(&rc, pPages); - if( pTab!=pOrphan ) recoverFreeTable(pTab); - } - shellFinalize(&rc, pLoop); - shellFinalize(&rc, pPages); - shellFinalize(&rc, pCells); - recoverFreeTable(pOrphan); + /* Figure out if an orphan table will be required. And if so, how many + ** user columns it should contain */ + shellPrepare(pState->db, &rc, + "SELECT coalesce(max(maxlen), -2) FROM recovery.map WHERE root>1" + , &pLoop + ); + if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pLoop) ){ + nOrphan = sqlite3_column_int(pLoop, 0); + } + shellFinalize(&rc, pLoop); + pLoop = 0; + + shellPrepare(pState->db, &rc, + "SELECT pgno FROM recovery.map WHERE root=?", &pPages + ); + + shellPrepare(pState->db, &rc, + "SELECT max(field), group_concat(shell_escape_crnl(quote" + "(case when (? AND field<0) then NULL else value end)" + "), ', ')" + ", min(field) " + "FROM sqlite_dbdata WHERE pgno = ? AND field != ?" + "GROUP BY cell", &pCells + ); + + /* Loop through each root page. */ + shellPrepare(pState->db, &rc, + "SELECT root, intkey, max(maxlen) FROM recovery.map" + " WHERE root>1 GROUP BY root, intkey ORDER BY root=(" + " SELECT rootpage FROM recovery.schema WHERE name='sqlite_sequence'" + ")", &pLoop + ); + while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pLoop) ){ + int iRoot = sqlite3_column_int(pLoop, 0); + int bIntkey = sqlite3_column_int(pLoop, 1); + int nCol = sqlite3_column_int(pLoop, 2); + int bNoop = 0; + RecoverTable *pTab; - /* The rest of the schema */ - if( rc==SQLITE_OK ){ - sqlite3_stmt *pStmt = 0; - shellPrepare(pState->db, &rc, - "SELECT sql, name FROM recovery.schema " - "WHERE sql NOT LIKE 'create table%'", &pStmt - ); - while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){ - const char *zSql = (const char*)sqlite3_column_text(pStmt, 0); - if( sqlite3_strnicmp(zSql, "create virt", 11)==0 ){ - const char *zName = (const char*)sqlite3_column_text(pStmt, 1); - char *zPrint = shellMPrintf(&rc, - "INSERT INTO sqlite_schema VALUES('table', %Q, %Q, 0, %Q)", - zName, zName, zSql - ); - raw_printf(pState->out, "%s;\n", zPrint); - sqlite3_free(zPrint); - }else{ - raw_printf(pState->out, "%s;\n", zSql); - } - } - shellFinalize(&rc, pStmt); + assert( bIntkey==0 || bIntkey==1 ); + pTab = recoverFindTable(pState, &rc, iRoot, bIntkey, nCol, &bNoop); + if( bNoop || rc ) continue; + if( pTab==0 ){ + if( pOrphan==0 ){ + pOrphan = recoverOrphanTable(pState, &rc, zLostAndFound, nOrphan); + } + pTab = pOrphan; + if( pTab==0 ) break; } - if( rc==SQLITE_OK ){ - raw_printf(pState->out, "PRAGMA writable_schema = off;\n"); - raw_printf(pState->out, "COMMIT;\n"); + if( 0==sqlite3_stricmp(pTab->zQuoted, "\"sqlite_sequence\"") ){ + raw_printf(pState->out, "DELETE FROM sqlite_sequence;\n"); } - sqlite3_exec(pState->db, "DETACH recovery", 0, 0, 0); - return rc; + sqlite3_bind_int(pPages, 1, iRoot); + if( bRowids==0 && pTab->iPk<0 ){ + sqlite3_bind_int(pCells, 1, 1); + }else{ + sqlite3_bind_int(pCells, 1, 0); + } + sqlite3_bind_int(pCells, 3, pTab->iPk); + + while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pPages) ){ + int iPgno = sqlite3_column_int(pPages, 0); + sqlite3_bind_int(pCells, 2, iPgno); + while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pCells) ){ + int nField = sqlite3_column_int(pCells, 0); + int iMin = sqlite3_column_int(pCells, 2); + const char *zVal = (const char*)sqlite3_column_text(pCells, 1); + + RecoverTable *pTab2 = pTab; + if( pTab!=pOrphan && (iMin<0)!=bIntkey ){ + if( pOrphan==0 ){ + pOrphan = recoverOrphanTable(pState, &rc, zLostAndFound, nOrphan); + } + pTab2 = pOrphan; + if( pTab2==0 ) break; + } + + nField = nField+1; + if( pTab2==pOrphan ){ + raw_printf(pState->out, + "INSERT INTO %s VALUES(%d, %d, %d, %s%s%s);\n", + pTab2->zQuoted, iRoot, iPgno, nField, + iMin<0 ? "" : "NULL, ", zVal, pTab2->azlCol[nField] + ); + }else{ + raw_printf(pState->out, "INSERT INTO %s(%s) VALUES( %s );\n", + pTab2->zQuoted, pTab2->azlCol[nField], zVal + ); + } + } + shellReset(&rc, pCells); + } + shellReset(&rc, pPages); + if( pTab!=pOrphan ) recoverFreeTable(pTab); + } + shellFinalize(&rc, pLoop); + shellFinalize(&rc, pPages); + shellFinalize(&rc, pCells); + recoverFreeTable(pOrphan); + + /* The rest of the schema */ + if( rc==SQLITE_OK ){ + sqlite3_stmt *pStmt = 0; + shellPrepare(pState->db, &rc, + "SELECT sql, name FROM recovery.schema " + "WHERE sql NOT LIKE 'create table%'", &pStmt + ); + while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){ + const char *zSql = (const char*)sqlite3_column_text(pStmt, 0); + if( sqlite3_strnicmp(zSql, "create virt", 11)==0 ){ + const char *zName = (const char*)sqlite3_column_text(pStmt, 1); + char *zPrint = shellMPrintf(&rc, + "INSERT INTO sqlite_schema VALUES('table', %Q, %Q, 0, %Q)", + zName, zName, zSql + ); + raw_printf(pState->out, "%s;\n", zPrint); + sqlite3_free(zPrint); + }else{ + raw_printf(pState->out, "%s;\n", zSql); + } + } + shellFinalize(&rc, pStmt); + } + + if( rc==SQLITE_OK ){ + raw_printf(pState->out, "PRAGMA writable_schema = off;\n"); + raw_printf(pState->out, "COMMIT;\n"); + } + sqlite3_exec(pState->db, "DETACH recovery", 0, 0, 0); + return rc; } #endif /* !(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB) */ @@ -18610,3140 +18610,3140 @@ static int recoverDatabaseCmd(ShellState *pState, int nArg, char **azArg){ ** Return 1 on error, 2 to exit, and 0 otherwise. */ static int do_meta_command(char *zLine, ShellState *p){ - int h = 1; - int nArg = 0; - int n, c; - int rc = 0; - char *azArg[52]; + int h = 1; + int nArg = 0; + int n, c; + int rc = 0; + char *azArg[52]; #ifndef SQLITE_OMIT_VIRTUALTABLE - if( p->expert.pExpert ){ - expertFinish(p, 1, 0); - } + if( p->expert.pExpert ){ + expertFinish(p, 1, 0); + } #endif - /* Parse the input line into tokens. + /* Parse the input line into tokens. */ - while( zLine[h] && nArgdb, shellAuth, p); - }else if( p->bSafeModePersist ){ - sqlite3_set_authorizer(p->db, safeModeAuth, p); - }else{ - sqlite3_set_authorizer(p->db, 0, 0); - } - }else + if( c=='a' && strncmp(azArg[0], "auth", n)==0 ){ + if( nArg!=2 ){ + raw_printf(stderr, "Usage: .auth ON|OFF\n"); + rc = 1; + goto meta_command_exit; + } + open_db(p, 0); + if( booleanValue(azArg[1]) ){ + sqlite3_set_authorizer(p->db, shellAuth, p); + }else if( p->bSafeModePersist ){ + sqlite3_set_authorizer(p->db, safeModeAuth, p); + }else{ + sqlite3_set_authorizer(p->db, 0, 0); + } + }else #endif #if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB) - if( c=='a' && strncmp(azArg[0], "archive", n)==0 ){ - open_db(p, 0); - failIfSafeMode(p, "cannot run .archive in safe mode"); - rc = arDotCommand(p, 0, azArg, nArg); - }else + if( c=='a' && strncmp(azArg[0], "archive", n)==0 ){ + open_db(p, 0); + failIfSafeMode(p, "cannot run .archive in safe mode"); + rc = arDotCommand(p, 0, azArg, nArg); + }else #endif - if( (c=='b' && n>=3 && strncmp(azArg[0], "backup", n)==0) - || (c=='s' && n>=3 && strncmp(azArg[0], "save", n)==0) - ){ - const char *zDestFile = 0; - const char *zDb = 0; - sqlite3 *pDest; - sqlite3_backup *pBackup; - int j; - int bAsync = 0; - const char *zVfs = 0; - failIfSafeMode(p, "cannot run .%s in safe mode", azArg[0]); - for(j=1; jdb, zDb); - if( pBackup==0 ){ - utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(pDest)); - close_db(pDest); - return 1; - } - while( (rc = sqlite3_backup_step(pBackup,100))==SQLITE_OK ){} - sqlite3_backup_finish(pBackup); - if( rc==SQLITE_DONE ){ - rc = 0; - }else{ - utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(pDest)); - rc = 1; - } - close_db(pDest); - }else - - if( c=='b' && n>=3 && strncmp(azArg[0], "bail", n)==0 ){ - if( nArg==2 ){ - bail_on_error = booleanValue(azArg[1]); - }else{ - raw_printf(stderr, "Usage: .bail on|off\n"); - rc = 1; - } - }else + if( (c=='b' && n>=3 && strncmp(azArg[0], "backup", n)==0) + || (c=='s' && n>=3 && strncmp(azArg[0], "save", n)==0) + ){ + const char *zDestFile = 0; + const char *zDb = 0; + sqlite3 *pDest; + sqlite3_backup *pBackup; + int j; + int bAsync = 0; + const char *zVfs = 0; + failIfSafeMode(p, "cannot run .%s in safe mode", azArg[0]); + for(j=1; jdb, zDb); + if( pBackup==0 ){ + utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(pDest)); + close_db(pDest); + return 1; + } + while( (rc = sqlite3_backup_step(pBackup,100))==SQLITE_OK ){} + sqlite3_backup_finish(pBackup); + if( rc==SQLITE_DONE ){ + rc = 0; + }else{ + utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(pDest)); + rc = 1; + } + close_db(pDest); + }else - if( c=='b' && n>=3 && strncmp(azArg[0], "binary", n)==0 ){ - if( nArg==2 ){ - if( booleanValue(azArg[1]) ){ - setBinaryMode(p->out, 1); - }else{ - setTextMode(p->out, 1); - } - }else{ - raw_printf(stderr, "Usage: .binary on|off\n"); - rc = 1; - } - }else + if( c=='b' && n>=3 && strncmp(azArg[0], "bail", n)==0 ){ + if( nArg==2 ){ + bail_on_error = booleanValue(azArg[1]); + }else{ + raw_printf(stderr, "Usage: .bail on|off\n"); + rc = 1; + } + }else + + if( c=='b' && n>=3 && strncmp(azArg[0], "binary", n)==0 ){ + if( nArg==2 ){ + if( booleanValue(azArg[1]) ){ + setBinaryMode(p->out, 1); + }else{ + setTextMode(p->out, 1); + } + }else{ + raw_printf(stderr, "Usage: .binary on|off\n"); + rc = 1; + } + }else - /* The undocumented ".breakpoint" command causes a call to the no-op + /* The undocumented ".breakpoint" command causes a call to the no-op ** routine named test_breakpoint(). */ - if( c=='b' && n>=3 && strncmp(azArg[0], "breakpoint", n)==0 ){ - test_breakpoint(); - }else + if( c=='b' && n>=3 && strncmp(azArg[0], "breakpoint", n)==0 ){ + test_breakpoint(); + }else - if( c=='c' && strcmp(azArg[0],"cd")==0 ){ - failIfSafeMode(p, "cannot run .cd in safe mode"); - if( nArg==2 ){ + if( c=='c' && strcmp(azArg[0],"cd")==0 ){ + failIfSafeMode(p, "cannot run .cd in safe mode"); + if( nArg==2 ){ #if defined(_WIN32) || defined(WIN32) - wchar_t *z = sqlite3_win32_utf8_to_unicode(azArg[1]); - rc = !SetCurrentDirectoryW(z); - sqlite3_free(z); + wchar_t *z = sqlite3_win32_utf8_to_unicode(azArg[1]); + rc = !SetCurrentDirectoryW(z); + sqlite3_free(z); #else - rc = chdir(azArg[1]); + rc = chdir(azArg[1]); #endif - if( rc ){ - utf8_printf(stderr, "Cannot change to directory \"%s\"\n", azArg[1]); - rc = 1; - } - }else{ - raw_printf(stderr, "Usage: .cd DIRECTORY\n"); - rc = 1; - } - }else + if( rc ){ + utf8_printf(stderr, "Cannot change to directory \"%s\"\n", azArg[1]); + rc = 1; + } + }else{ + raw_printf(stderr, "Usage: .cd DIRECTORY\n"); + rc = 1; + } + }else - if( c=='c' && n>=3 && strncmp(azArg[0], "changes", n)==0 ){ - if( nArg==2 ){ - setOrClearFlag(p, SHFLG_CountChanges, azArg[1]); - }else{ - raw_printf(stderr, "Usage: .changes on|off\n"); - rc = 1; - } - }else + if( c=='c' && n>=3 && strncmp(azArg[0], "changes", n)==0 ){ + if( nArg==2 ){ + setOrClearFlag(p, SHFLG_CountChanges, azArg[1]); + }else{ + raw_printf(stderr, "Usage: .changes on|off\n"); + rc = 1; + } + }else - /* Cancel output redirection, if it is currently set (by .testcase) + /* Cancel output redirection, if it is currently set (by .testcase) ** Then read the content of the testcase-out.txt file and compare against ** azArg[1]. If there are differences, report an error and exit. */ - if( c=='c' && n>=3 && strncmp(azArg[0], "check", n)==0 ){ - char *zRes = 0; - output_reset(p); - if( nArg!=2 ){ - raw_printf(stderr, "Usage: .check GLOB-PATTERN\n"); - rc = 2; - }else if( (zRes = readFile("testcase-out.txt", 0))==0 ){ - raw_printf(stderr, "Error: cannot read 'testcase-out.txt'\n"); - rc = 2; - }else if( testcase_glob(azArg[1],zRes)==0 ){ - utf8_printf(stderr, - "testcase-%s FAILED\n Expected: [%s]\n Got: [%s]\n", - p->zTestcase, azArg[1], zRes); - rc = 1; - }else{ - utf8_printf(stdout, "testcase-%s ok\n", p->zTestcase); - p->nCheck++; - } - sqlite3_free(zRes); - }else - - if( c=='c' && strncmp(azArg[0], "clone", n)==0 ){ - failIfSafeMode(p, "cannot run .clone in safe mode"); - if( nArg==2 ){ - tryToClone(p, azArg[1]); - }else{ - raw_printf(stderr, "Usage: .clone FILENAME\n"); - rc = 1; - } - }else - - if( c=='c' && strncmp(azArg[0], "connection", n)==0 ){ - if( nArg==1 ){ - /* List available connections */ - int i; - for(i=0; iaAuxDb); i++){ - const char *zFile = p->aAuxDb[i].zDbFilename; - if( p->aAuxDb[i].db==0 && p->pAuxDb!=&p->aAuxDb[i] ){ - zFile = "(not open)"; - }else if( zFile==0 ){ - zFile = "(memory)"; - }else if( zFile[0]==0 ){ - zFile = "(temporary-file)"; - } - if( p->pAuxDb == &p->aAuxDb[i] ){ - utf8_printf(stdout, "ACTIVE %d: %s\n", i, zFile); - }else if( p->aAuxDb[i].db!=0 ){ - utf8_printf(stdout, " %d: %s\n", i, zFile); - } - } - }else if( nArg==2 && IsDigit(azArg[1][0]) && azArg[1][1]==0 ){ - int i = azArg[1][0] - '0'; - if( p->pAuxDb != &p->aAuxDb[i] && i>=0 && iaAuxDb) ){ - p->pAuxDb->db = p->db; - p->pAuxDb = &p->aAuxDb[i]; - globalDb = p->db = p->pAuxDb->db; - p->pAuxDb->db = 0; - } - }else if( nArg==3 && strcmp(azArg[1], "close")==0 - && IsDigit(azArg[2][0]) && azArg[2][1]==0 ){ - int i = azArg[2][0] - '0'; - if( i<0 || i>=ArraySize(p->aAuxDb) ){ - /* No-op */ - }else if( p->pAuxDb == &p->aAuxDb[i] ){ - raw_printf(stderr, "cannot close the active database connection\n"); - rc = 1; - }else if( p->aAuxDb[i].db ){ - session_close_all(p, i); - close_db(p->aAuxDb[i].db); - p->aAuxDb[i].db = 0; - } - }else{ - raw_printf(stderr, "Usage: .connection [close] [CONNECTION-NUMBER]\n"); - rc = 1; - } - }else - - if( c=='d' && n>1 && strncmp(azArg[0], "databases", n)==0 ){ - char **azName = 0; - int nName = 0; - sqlite3_stmt *pStmt; - int i; - open_db(p, 0); - rc = sqlite3_prepare_v2(p->db, "PRAGMA database_list", -1, &pStmt, 0); - if( rc ){ - utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db)); - rc = 1; - }else{ - while( sqlite3_step(pStmt)==SQLITE_ROW ){ - const char *zSchema = (const char *)sqlite3_column_text(pStmt,1); - const char *zFile = (const char*)sqlite3_column_text(pStmt,2); - azName = sqlite3_realloc(azName, (nName+1)*2*sizeof(char*)); - if( azName==0 ){ shell_out_of_memory(); /* Does not return */ } - azName[nName*2] = strdup(zSchema); - azName[nName*2+1] = strdup(zFile); - nName++; - } - } - sqlite3_finalize(pStmt); - for(i=0; idb, azName[i*2]); - int bRdonly = sqlite3_db_readonly(p->db, azName[i*2]); - const char *z = azName[i*2+1]; - utf8_printf(p->out, "%s: %s %s%s\n", - azName[i*2], - z && z[0] ? z : "\"\"", - bRdonly ? "r/o" : "r/w", - eTxn==SQLITE_TXN_NONE ? "" : - eTxn==SQLITE_TXN_READ ? " read-txn" : " write-txn"); - free(azName[i*2]); - free(azName[i*2+1]); - } - sqlite3_free(azName); - }else - - if( c=='d' && n>=3 && strncmp(azArg[0], "dbconfig", n)==0 ){ - static const struct DbConfigChoices { - const char *zName; - int op; - } aDbConfig[] = { - { "defensive", SQLITE_DBCONFIG_DEFENSIVE }, - { "dqs_ddl", SQLITE_DBCONFIG_DQS_DDL }, - { "dqs_dml", SQLITE_DBCONFIG_DQS_DML }, - { "enable_fkey", SQLITE_DBCONFIG_ENABLE_FKEY }, - { "enable_qpsg", SQLITE_DBCONFIG_ENABLE_QPSG }, - { "enable_trigger", SQLITE_DBCONFIG_ENABLE_TRIGGER }, - { "enable_view", SQLITE_DBCONFIG_ENABLE_VIEW }, - { "fts3_tokenizer", SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER }, - { "legacy_alter_table", SQLITE_DBCONFIG_LEGACY_ALTER_TABLE }, - { "legacy_file_format", SQLITE_DBCONFIG_LEGACY_FILE_FORMAT }, - { "load_extension", SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION }, - { "no_ckpt_on_close", SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE }, - { "reset_database", SQLITE_DBCONFIG_RESET_DATABASE }, - { "trigger_eqp", SQLITE_DBCONFIG_TRIGGER_EQP }, - { "trusted_schema", SQLITE_DBCONFIG_TRUSTED_SCHEMA }, - { "writable_schema", SQLITE_DBCONFIG_WRITABLE_SCHEMA }, - }; - int ii, v; - open_db(p, 0); - for(ii=0; ii1 && strcmp(azArg[1], aDbConfig[ii].zName)!=0 ) continue; - if( nArg>=3 ){ - sqlite3_db_config(p->db, aDbConfig[ii].op, booleanValue(azArg[2]), 0); - } - sqlite3_db_config(p->db, aDbConfig[ii].op, -1, &v); - utf8_printf(p->out, "%19s %s\n", aDbConfig[ii].zName, v ? "on" : "off"); - if( nArg>1 ) break; - } - if( nArg>1 && ii==ArraySize(aDbConfig) ){ - utf8_printf(stderr, "Error: unknown dbconfig \"%s\"\n", azArg[1]); - utf8_printf(stderr, "Enter \".dbconfig\" with no arguments for a list\n"); - } - }else + if( c=='c' && n>=3 && strncmp(azArg[0], "check", n)==0 ){ + char *zRes = 0; + output_reset(p); + if( nArg!=2 ){ + raw_printf(stderr, "Usage: .check GLOB-PATTERN\n"); + rc = 2; + }else if( (zRes = readFile("testcase-out.txt", 0))==0 ){ + raw_printf(stderr, "Error: cannot read 'testcase-out.txt'\n"); + rc = 2; + }else if( testcase_glob(azArg[1],zRes)==0 ){ + utf8_printf(stderr, + "testcase-%s FAILED\n Expected: [%s]\n Got: [%s]\n", + p->zTestcase, azArg[1], zRes); + rc = 1; + }else{ + utf8_printf(stdout, "testcase-%s ok\n", p->zTestcase); + p->nCheck++; + } + sqlite3_free(zRes); + }else + + if( c=='c' && strncmp(azArg[0], "clone", n)==0 ){ + failIfSafeMode(p, "cannot run .clone in safe mode"); + if( nArg==2 ){ + tryToClone(p, azArg[1]); + }else{ + raw_printf(stderr, "Usage: .clone FILENAME\n"); + rc = 1; + } + }else + + if( c=='c' && strncmp(azArg[0], "connection", n)==0 ){ + if( nArg==1 ){ + /* List available connections */ + int i; + for(i=0; iaAuxDb); i++){ + const char *zFile = p->aAuxDb[i].zDbFilename; + if( p->aAuxDb[i].db==0 && p->pAuxDb!=&p->aAuxDb[i] ){ + zFile = "(not open)"; + }else if( zFile==0 ){ + zFile = "(memory)"; + }else if( zFile[0]==0 ){ + zFile = "(temporary-file)"; + } + if( p->pAuxDb == &p->aAuxDb[i] ){ + utf8_printf(stdout, "ACTIVE %d: %s\n", i, zFile); + }else if( p->aAuxDb[i].db!=0 ){ + utf8_printf(stdout, " %d: %s\n", i, zFile); + } + } + }else if( nArg==2 && IsDigit(azArg[1][0]) && azArg[1][1]==0 ){ + int i = azArg[1][0] - '0'; + if( p->pAuxDb != &p->aAuxDb[i] && i>=0 && iaAuxDb) ){ + p->pAuxDb->db = p->db; + p->pAuxDb = &p->aAuxDb[i]; + globalDb = p->db = p->pAuxDb->db; + p->pAuxDb->db = 0; + } + }else if( nArg==3 && strcmp(azArg[1], "close")==0 + && IsDigit(azArg[2][0]) && azArg[2][1]==0 ){ + int i = azArg[2][0] - '0'; + if( i<0 || i>=ArraySize(p->aAuxDb) ){ + /* No-op */ + }else if( p->pAuxDb == &p->aAuxDb[i] ){ + raw_printf(stderr, "cannot close the active database connection\n"); + rc = 1; + }else if( p->aAuxDb[i].db ){ + session_close_all(p, i); + close_db(p->aAuxDb[i].db); + p->aAuxDb[i].db = 0; + } + }else{ + raw_printf(stderr, "Usage: .connection [close] [CONNECTION-NUMBER]\n"); + rc = 1; + } + }else - if( c=='d' && n>=3 && strncmp(azArg[0], "dbinfo", n)==0 ){ - rc = shell_dbinfo_command(p, nArg, azArg); - }else + if( c=='d' && n>1 && strncmp(azArg[0], "databases", n)==0 ){ + char **azName = 0; + int nName = 0; + sqlite3_stmt *pStmt; + int i; + open_db(p, 0); + rc = sqlite3_prepare_v2(p->db, "PRAGMA database_list", -1, &pStmt, 0); + if( rc ){ + utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db)); + rc = 1; + }else{ + while( sqlite3_step(pStmt)==SQLITE_ROW ){ + const char *zSchema = (const char *)sqlite3_column_text(pStmt,1); + const char *zFile = (const char*)sqlite3_column_text(pStmt,2); + azName = sqlite3_realloc(azName, (nName+1)*2*sizeof(char*)); + if( azName==0 ){ shell_out_of_memory(); /* Does not return */ } + azName[nName*2] = strdup(zSchema); + azName[nName*2+1] = strdup(zFile); + nName++; + } + } + sqlite3_finalize(pStmt); + for(i=0; idb, azName[i*2]); + int bRdonly = sqlite3_db_readonly(p->db, azName[i*2]); + const char *z = azName[i*2+1]; + utf8_printf(p->out, "%s: %s %s%s\n", + azName[i*2], + z && z[0] ? z : "\"\"", + bRdonly ? "r/o" : "r/w", + eTxn==SQLITE_TXN_NONE ? "" : + eTxn==SQLITE_TXN_READ ? " read-txn" : " write-txn"); + free(azName[i*2]); + free(azName[i*2+1]); + } + sqlite3_free(azName); + }else + + if( c=='d' && n>=3 && strncmp(azArg[0], "dbconfig", n)==0 ){ + static const struct DbConfigChoices { + const char *zName; + int op; + } aDbConfig[] = { + { "defensive", SQLITE_DBCONFIG_DEFENSIVE }, + { "dqs_ddl", SQLITE_DBCONFIG_DQS_DDL }, + { "dqs_dml", SQLITE_DBCONFIG_DQS_DML }, + { "enable_fkey", SQLITE_DBCONFIG_ENABLE_FKEY }, + { "enable_qpsg", SQLITE_DBCONFIG_ENABLE_QPSG }, + { "enable_trigger", SQLITE_DBCONFIG_ENABLE_TRIGGER }, + { "enable_view", SQLITE_DBCONFIG_ENABLE_VIEW }, + { "fts3_tokenizer", SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER }, + { "legacy_alter_table", SQLITE_DBCONFIG_LEGACY_ALTER_TABLE }, + { "legacy_file_format", SQLITE_DBCONFIG_LEGACY_FILE_FORMAT }, + { "load_extension", SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION }, + { "no_ckpt_on_close", SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE }, + { "reset_database", SQLITE_DBCONFIG_RESET_DATABASE }, + { "trigger_eqp", SQLITE_DBCONFIG_TRIGGER_EQP }, + { "trusted_schema", SQLITE_DBCONFIG_TRUSTED_SCHEMA }, + { "writable_schema", SQLITE_DBCONFIG_WRITABLE_SCHEMA }, + }; + int ii, v; + open_db(p, 0); + for(ii=0; ii1 && strcmp(azArg[1], aDbConfig[ii].zName)!=0 ) continue; + if( nArg>=3 ){ + sqlite3_db_config(p->db, aDbConfig[ii].op, booleanValue(azArg[2]), 0); + } + sqlite3_db_config(p->db, aDbConfig[ii].op, -1, &v); + utf8_printf(p->out, "%19s %s\n", aDbConfig[ii].zName, v ? "on" : "off"); + if( nArg>1 ) break; + } + if( nArg>1 && ii==ArraySize(aDbConfig) ){ + utf8_printf(stderr, "Error: unknown dbconfig \"%s\"\n", azArg[1]); + utf8_printf(stderr, "Enter \".dbconfig\" with no arguments for a list\n"); + } + }else + + if( c=='d' && n>=3 && strncmp(azArg[0], "dbinfo", n)==0 ){ + rc = shell_dbinfo_command(p, nArg, azArg); + }else #if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB) - if( c=='r' && strncmp(azArg[0], "recover", n)==0 ){ - open_db(p, 0); - rc = recoverDatabaseCmd(p, nArg, azArg); - }else + if( c=='r' && strncmp(azArg[0], "recover", n)==0 ){ + open_db(p, 0); + rc = recoverDatabaseCmd(p, nArg, azArg); + }else #endif /* !(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB) */ - if( c=='d' && strncmp(azArg[0], "dump", n)==0 ){ - char *zLike = 0; - char *zSql; - int i; - int savedShowHeader = p->showHeader; - int savedShellFlags = p->shellFlgs; - ShellClearFlag(p, - SHFLG_PreserveRowid|SHFLG_Newlines|SHFLG_Echo - |SHFLG_DumpDataOnly|SHFLG_DumpNoSys); - for(i=1; ishowHeader; + int savedShellFlags = p->shellFlgs; + ShellClearFlag(p, + SHFLG_PreserveRowid|SHFLG_Newlines|SHFLG_Echo + |SHFLG_DumpDataOnly|SHFLG_DumpNoSys); + for(i=1; ishellFlgs & SHFLG_DumpDataOnly)==0 ){ - /* When playing back a "dump", the content might appear in an order + char *zExpr = sqlite3_mprintf( + "name LIKE %Q ESCAPE '\\' OR EXISTS (" + " SELECT 1 FROM sqlite_schema WHERE " + " name LIKE %Q ESCAPE '\\' AND" + " sql LIKE 'CREATE VIRTUAL TABLE%%' AND" + " substr(o.name, 1, length(name)+1) == (name||'_')" + ")", azArg[i], azArg[i] + ); + + if( zLike ){ + zLike = sqlite3_mprintf("%z OR %z", zLike, zExpr); + }else{ + zLike = zExpr; + } + } + } + + open_db(p, 0); + + if( (p->shellFlgs & SHFLG_DumpDataOnly)==0 ){ + /* When playing back a "dump", the content might appear in an order ** which causes immediate foreign key constraints to be violated. ** So disable foreign-key constraint enforcement to prevent problems. */ - raw_printf(p->out, "PRAGMA foreign_keys=OFF;\n"); - raw_printf(p->out, "BEGIN TRANSACTION;\n"); - } - p->writableSchema = 0; - p->showHeader = 0; - /* Set writable_schema=ON since doing so forces SQLite to initialize + raw_printf(p->out, "PRAGMA foreign_keys=OFF;\n"); + raw_printf(p->out, "BEGIN TRANSACTION;\n"); + } + p->writableSchema = 0; + p->showHeader = 0; + /* Set writable_schema=ON since doing so forces SQLite to initialize ** as much of the schema as it can even if the sqlite_schema table is ** corrupt. */ - sqlite3_exec(p->db, "SAVEPOINT dump; PRAGMA writable_schema=ON", 0, 0, 0); - p->nErr = 0; - if( zLike==0 ) zLike = sqlite3_mprintf("true"); - zSql = sqlite3_mprintf( - "SELECT name, type, sql FROM sqlite_schema AS o " - "WHERE (%s) AND type=='table'" - " AND sql NOT NULL" - " ORDER BY tbl_name='sqlite_sequence', rowid", - zLike - ); - run_schema_dump_query(p,zSql); - sqlite3_free(zSql); - if( (p->shellFlgs & SHFLG_DumpDataOnly)==0 ){ - zSql = sqlite3_mprintf( - "SELECT sql FROM sqlite_schema AS o " - "WHERE (%s) AND sql NOT NULL" - " AND type IN ('index','trigger','view')", - zLike - ); - run_table_dump_query(p, zSql); - sqlite3_free(zSql); - } - sqlite3_free(zLike); - if( p->writableSchema ){ - raw_printf(p->out, "PRAGMA writable_schema=OFF;\n"); - p->writableSchema = 0; - } - sqlite3_exec(p->db, "PRAGMA writable_schema=OFF;", 0, 0, 0); - sqlite3_exec(p->db, "RELEASE dump;", 0, 0, 0); - if( (p->shellFlgs & SHFLG_DumpDataOnly)==0 ){ - raw_printf(p->out, p->nErr?"ROLLBACK; -- due to errors\n":"COMMIT;\n"); - } - p->showHeader = savedShowHeader; - p->shellFlgs = savedShellFlags; - }else - - if( c=='e' && strncmp(azArg[0], "echo", n)==0 ){ - if( nArg==2 ){ - setOrClearFlag(p, SHFLG_Echo, azArg[1]); - }else{ - raw_printf(stderr, "Usage: .echo on|off\n"); - rc = 1; - } - }else - - if( c=='e' && strncmp(azArg[0], "eqp", n)==0 ){ - if( nArg==2 ){ - p->autoEQPtest = 0; - if( p->autoEQPtrace ){ - if( p->db ) sqlite3_exec(p->db, "PRAGMA vdbe_trace=OFF;", 0, 0, 0); - p->autoEQPtrace = 0; - } - if( strcmp(azArg[1],"full")==0 ){ - p->autoEQP = AUTOEQP_full; - }else if( strcmp(azArg[1],"trigger")==0 ){ - p->autoEQP = AUTOEQP_trigger; + sqlite3_exec(p->db, "SAVEPOINT dump; PRAGMA writable_schema=ON", 0, 0, 0); + p->nErr = 0; + if( zLike==0 ) zLike = sqlite3_mprintf("true"); + zSql = sqlite3_mprintf( + "SELECT name, type, sql FROM sqlite_schema AS o " + "WHERE (%s) AND type=='table'" + " AND sql NOT NULL" + " ORDER BY tbl_name='sqlite_sequence', rowid", + zLike + ); + run_schema_dump_query(p,zSql); + sqlite3_free(zSql); + if( (p->shellFlgs & SHFLG_DumpDataOnly)==0 ){ + zSql = sqlite3_mprintf( + "SELECT sql FROM sqlite_schema AS o " + "WHERE (%s) AND sql NOT NULL" + " AND type IN ('index','trigger','view')", + zLike + ); + run_table_dump_query(p, zSql); + sqlite3_free(zSql); + } + sqlite3_free(zLike); + if( p->writableSchema ){ + raw_printf(p->out, "PRAGMA writable_schema=OFF;\n"); + p->writableSchema = 0; + } + sqlite3_exec(p->db, "PRAGMA writable_schema=OFF;", 0, 0, 0); + sqlite3_exec(p->db, "RELEASE dump;", 0, 0, 0); + if( (p->shellFlgs & SHFLG_DumpDataOnly)==0 ){ + raw_printf(p->out, p->nErr?"ROLLBACK; -- due to errors\n":"COMMIT;\n"); + } + p->showHeader = savedShowHeader; + p->shellFlgs = savedShellFlags; + }else + + if( c=='e' && strncmp(azArg[0], "echo", n)==0 ){ + if( nArg==2 ){ + setOrClearFlag(p, SHFLG_Echo, azArg[1]); + }else{ + raw_printf(stderr, "Usage: .echo on|off\n"); + rc = 1; + } + }else + + if( c=='e' && strncmp(azArg[0], "eqp", n)==0 ){ + if( nArg==2 ){ + p->autoEQPtest = 0; + if( p->autoEQPtrace ){ + if( p->db ) sqlite3_exec(p->db, "PRAGMA vdbe_trace=OFF;", 0, 0, 0); + p->autoEQPtrace = 0; + } + if( strcmp(azArg[1],"full")==0 ){ + p->autoEQP = AUTOEQP_full; + }else if( strcmp(azArg[1],"trigger")==0 ){ + p->autoEQP = AUTOEQP_trigger; #ifdef SQLITE_DEBUG - }else if( strcmp(azArg[1],"test")==0 ){ - p->autoEQP = AUTOEQP_on; - p->autoEQPtest = 1; - }else if( strcmp(azArg[1],"trace")==0 ){ - p->autoEQP = AUTOEQP_full; - p->autoEQPtrace = 1; - open_db(p, 0); - sqlite3_exec(p->db, "SELECT name FROM sqlite_schema LIMIT 1", 0, 0, 0); - sqlite3_exec(p->db, "PRAGMA vdbe_trace=ON;", 0, 0, 0); + }else if( strcmp(azArg[1],"test")==0 ){ + p->autoEQP = AUTOEQP_on; + p->autoEQPtest = 1; + }else if( strcmp(azArg[1],"trace")==0 ){ + p->autoEQP = AUTOEQP_full; + p->autoEQPtrace = 1; + open_db(p, 0); + sqlite3_exec(p->db, "SELECT name FROM sqlite_schema LIMIT 1", 0, 0, 0); + sqlite3_exec(p->db, "PRAGMA vdbe_trace=ON;", 0, 0, 0); #endif - }else{ - p->autoEQP = (u8)booleanValue(azArg[1]); - } - }else{ - raw_printf(stderr, "Usage: .eqp off|on|trace|trigger|full\n"); - rc = 1; - } - }else - - if( c=='e' && strncmp(azArg[0], "exit", n)==0 ){ - if( nArg>1 && (rc = (int)integerValue(azArg[1]))!=0 ) exit(rc); - rc = 2; - }else - - /* The ".explain" command is automatic now. It is largely pointless. It + }else{ + p->autoEQP = (u8)booleanValue(azArg[1]); + } + }else{ + raw_printf(stderr, "Usage: .eqp off|on|trace|trigger|full\n"); + rc = 1; + } + }else + + if( c=='e' && strncmp(azArg[0], "exit", n)==0 ){ + if( nArg>1 && (rc = (int)integerValue(azArg[1]))!=0 ) exit(rc); + rc = 2; + }else + + /* The ".explain" command is automatic now. It is largely pointless. It ** retained purely for backwards compatibility */ - if( c=='e' && strncmp(azArg[0], "explain", n)==0 ){ - int val = 1; - if( nArg>=2 ){ - if( strcmp(azArg[1],"auto")==0 ){ - val = 99; - }else{ - val = booleanValue(azArg[1]); - } - } - if( val==1 && p->mode!=MODE_Explain ){ - p->normalMode = p->mode; - p->mode = MODE_Explain; - p->autoExplain = 0; - }else if( val==0 ){ - if( p->mode==MODE_Explain ) p->mode = p->normalMode; - p->autoExplain = 0; - }else if( val==99 ){ - if( p->mode==MODE_Explain ) p->mode = p->normalMode; - p->autoExplain = 1; - } - }else + if( c=='e' && strncmp(azArg[0], "explain", n)==0 ){ + int val = 1; + if( nArg>=2 ){ + if( strcmp(azArg[1],"auto")==0 ){ + val = 99; + }else{ + val = booleanValue(azArg[1]); + } + } + if( val==1 && p->mode!=MODE_Explain ){ + p->normalMode = p->mode; + p->mode = MODE_Explain; + p->autoExplain = 0; + }else if( val==0 ){ + if( p->mode==MODE_Explain ) p->mode = p->normalMode; + p->autoExplain = 0; + }else if( val==99 ){ + if( p->mode==MODE_Explain ) p->mode = p->normalMode; + p->autoExplain = 1; + } + }else #ifndef SQLITE_OMIT_VIRTUALTABLE - if( c=='e' && strncmp(azArg[0], "expert", n)==0 ){ - open_db(p, 0); - expertDotCommand(p, azArg, nArg); - }else + if( c=='e' && strncmp(azArg[0], "expert", n)==0 ){ + open_db(p, 0); + expertDotCommand(p, azArg, nArg); + }else #endif - if( c=='f' && strncmp(azArg[0], "filectrl", n)==0 ){ - static const struct { - const char *zCtrlName; /* Name of a test-control option */ - int ctrlCode; /* Integer code for that option */ - const char *zUsage; /* Usage notes */ - } aCtrl[] = { - { "chunk_size", SQLITE_FCNTL_CHUNK_SIZE, "SIZE" }, - { "data_version", SQLITE_FCNTL_DATA_VERSION, "" }, - { "has_moved", SQLITE_FCNTL_HAS_MOVED, "" }, - { "lock_timeout", SQLITE_FCNTL_LOCK_TIMEOUT, "MILLISEC" }, - { "persist_wal", SQLITE_FCNTL_PERSIST_WAL, "[BOOLEAN]" }, - /* { "pragma", SQLITE_FCNTL_PRAGMA, "NAME ARG" },*/ - { "psow", SQLITE_FCNTL_POWERSAFE_OVERWRITE, "[BOOLEAN]" }, - { "reserve_bytes", SQLITE_FCNTL_RESERVE_BYTES, "[N]" }, - { "size_limit", SQLITE_FCNTL_SIZE_LIMIT, "[LIMIT]" }, - { "tempfilename", SQLITE_FCNTL_TEMPFILENAME, "" }, - /* { "win32_av_retry", SQLITE_FCNTL_WIN32_AV_RETRY, "COUNT DELAY" },*/ - }; - int filectrl = -1; - int iCtrl = -1; - sqlite3_int64 iRes = 0; /* Integer result to display if rc2==1 */ - int isOk = 0; /* 0: usage 1: %lld 2: no-result */ - int n2, i; - const char *zCmd = 0; - const char *zSchema = 0; - - open_db(p, 0); - zCmd = nArg>=2 ? azArg[1] : "help"; - - if( zCmd[0]=='-' - && (strcmp(zCmd,"--schema")==0 || strcmp(zCmd,"-schema")==0) - && nArg>=4 - ){ - zSchema = azArg[2]; - for(i=3; iout, "Available file-controls:\n"); - for(i=0; iout, " .filectrl %s %s\n", - aCtrl[i].zCtrlName, aCtrl[i].zUsage); - } - rc = 1; - goto meta_command_exit; - } - - /* convert filectrl text option to value. allow any unique prefix + if( c=='f' && strncmp(azArg[0], "filectrl", n)==0 ){ + static const struct { + const char *zCtrlName; /* Name of a test-control option */ + int ctrlCode; /* Integer code for that option */ + const char *zUsage; /* Usage notes */ + } aCtrl[] = { + { "chunk_size", SQLITE_FCNTL_CHUNK_SIZE, "SIZE" }, + { "data_version", SQLITE_FCNTL_DATA_VERSION, "" }, + { "has_moved", SQLITE_FCNTL_HAS_MOVED, "" }, + { "lock_timeout", SQLITE_FCNTL_LOCK_TIMEOUT, "MILLISEC" }, + { "persist_wal", SQLITE_FCNTL_PERSIST_WAL, "[BOOLEAN]" }, + /* { "pragma", SQLITE_FCNTL_PRAGMA, "NAME ARG" },*/ + { "psow", SQLITE_FCNTL_POWERSAFE_OVERWRITE, "[BOOLEAN]" }, + { "reserve_bytes", SQLITE_FCNTL_RESERVE_BYTES, "[N]" }, + { "size_limit", SQLITE_FCNTL_SIZE_LIMIT, "[LIMIT]" }, + { "tempfilename", SQLITE_FCNTL_TEMPFILENAME, "" }, + /* { "win32_av_retry", SQLITE_FCNTL_WIN32_AV_RETRY, "COUNT DELAY" },*/ + }; + int filectrl = -1; + int iCtrl = -1; + sqlite3_int64 iRes = 0; /* Integer result to display if rc2==1 */ + int isOk = 0; /* 0: usage 1: %lld 2: no-result */ + int n2, i; + const char *zCmd = 0; + const char *zSchema = 0; + + open_db(p, 0); + zCmd = nArg>=2 ? azArg[1] : "help"; + + if( zCmd[0]=='-' + && (strcmp(zCmd,"--schema")==0 || strcmp(zCmd,"-schema")==0) + && nArg>=4 + ){ + zSchema = azArg[2]; + for(i=3; iout, "Available file-controls:\n"); + for(i=0; iout, " .filectrl %s %s\n", + aCtrl[i].zCtrlName, aCtrl[i].zUsage); + } + rc = 1; + goto meta_command_exit; + } + + /* convert filectrl text option to value. allow any unique prefix ** of the option name, or a numerical value. */ - n2 = strlen30(zCmd); - for(i=0; idb, zSchema, SQLITE_FCNTL_SIZE_LIMIT, &iRes); - isOk = 1; - break; - } - case SQLITE_FCNTL_LOCK_TIMEOUT: - case SQLITE_FCNTL_CHUNK_SIZE: { - int x; - if( nArg!=3 ) break; - x = (int)integerValue(azArg[2]); - sqlite3_file_control(p->db, zSchema, filectrl, &x); - isOk = 2; - break; - } - case SQLITE_FCNTL_PERSIST_WAL: - case SQLITE_FCNTL_POWERSAFE_OVERWRITE: { - int x; - if( nArg!=2 && nArg!=3 ) break; - x = nArg==3 ? booleanValue(azArg[2]) : -1; - sqlite3_file_control(p->db, zSchema, filectrl, &x); - iRes = x; - isOk = 1; - break; - } - case SQLITE_FCNTL_DATA_VERSION: - case SQLITE_FCNTL_HAS_MOVED: { - int x; - if( nArg!=2 ) break; - sqlite3_file_control(p->db, zSchema, filectrl, &x); - iRes = x; - isOk = 1; - break; - } - case SQLITE_FCNTL_TEMPFILENAME: { - char *z = 0; - if( nArg!=2 ) break; - sqlite3_file_control(p->db, zSchema, filectrl, &z); - if( z ){ - utf8_printf(p->out, "%s\n", z); - sqlite3_free(z); - } - isOk = 2; - break; - } - case SQLITE_FCNTL_RESERVE_BYTES: { - int x; - if( nArg>=3 ){ - x = atoi(azArg[2]); - sqlite3_file_control(p->db, zSchema, filectrl, &x); - } - x = -1; - sqlite3_file_control(p->db, zSchema, filectrl, &x); - utf8_printf(p->out,"%d\n", x); - isOk = 2; - break; - } - } - } - if( isOk==0 && iCtrl>=0 ){ - utf8_printf(p->out, "Usage: .filectrl %s %s\n", zCmd,aCtrl[iCtrl].zUsage); - rc = 1; - }else if( isOk==1 ){ - char zBuf[100]; - sqlite3_snprintf(sizeof(zBuf), zBuf, "%lld", iRes); - raw_printf(p->out, "%s\n", zBuf); - } - }else - - if( c=='f' && strncmp(azArg[0], "fullschema", n)==0 ){ - ShellState data; - int doStats = 0; - memcpy(&data, p, sizeof(data)); - data.showHeader = 0; - data.cMode = data.mode = MODE_Semi; - if( nArg==2 && optionMatch(azArg[1], "indent") ){ - data.cMode = data.mode = MODE_Pretty; - nArg = 1; - } - if( nArg!=1 ){ - raw_printf(stderr, "Usage: .fullschema ?--indent?\n"); - rc = 1; - goto meta_command_exit; - } - open_db(p, 0); - rc = sqlite3_exec(p->db, - "SELECT sql FROM" - " (SELECT sql sql, type type, tbl_name tbl_name, name name, rowid x" - " FROM sqlite_schema UNION ALL" - " SELECT sql, type, tbl_name, name, rowid FROM sqlite_temp_schema) " - "WHERE type!='meta' AND sql NOTNULL AND name NOT LIKE 'sqlite_%' " - "ORDER BY x", - callback, &data, 0 - ); - if( rc==SQLITE_OK ){ - sqlite3_stmt *pStmt; - rc = sqlite3_prepare_v2(p->db, - "SELECT rowid FROM sqlite_schema" - " WHERE name GLOB 'sqlite_stat[134]'", - -1, &pStmt, 0); - doStats = sqlite3_step(pStmt)==SQLITE_ROW; - sqlite3_finalize(pStmt); - } - if( doStats==0 ){ - raw_printf(p->out, "/* No STAT tables available */\n"); - }else{ - raw_printf(p->out, "ANALYZE sqlite_schema;\n"); - data.cMode = data.mode = MODE_Insert; - data.zDestTable = "sqlite_stat1"; - shell_exec(&data, "SELECT * FROM sqlite_stat1", 0); - data.zDestTable = "sqlite_stat4"; - shell_exec(&data, "SELECT * FROM sqlite_stat4", 0); - raw_printf(p->out, "ANALYZE sqlite_schema;\n"); - } - }else - - if( c=='h' && strncmp(azArg[0], "headers", n)==0 ){ - if( nArg==2 ){ - p->showHeader = booleanValue(azArg[1]); - p->shellFlgs |= SHFLG_HeaderSet; - }else{ - raw_printf(stderr, "Usage: .headers on|off\n"); - rc = 1; - } - }else - - if( c=='h' && strncmp(azArg[0], "help", n)==0 ){ - if( nArg>=2 ){ - n = showHelp(p->out, azArg[1]); - if( n==0 ){ - utf8_printf(p->out, "Nothing matches '%s'\n", azArg[1]); - } - }else{ - showHelp(p->out, 0); - } - }else - - if( c=='i' && strncmp(azArg[0], "import", n)==0 ){ - char *zTable = 0; /* Insert data into this table */ - char *zFile = 0; /* Name of file to extra content from */ - sqlite3_stmt *pStmt = NULL; /* A statement */ - int nCol; /* Number of columns in the table */ - int nByte; /* Number of bytes in an SQL string */ - int i, j; /* Loop counters */ - int needCommit; /* True to COMMIT or ROLLBACK at end */ - int nSep; /* Number of bytes in p->colSeparator[] */ - char *zSql; /* An SQL statement */ - ImportCtx sCtx; /* Reader context */ - char *(SQLITE_CDECL *xRead)(ImportCtx*); /* Func to read one value */ - int eVerbose = 0; /* Larger for more console output */ - int nSkip = 0; /* Initial lines to skip */ - int useOutputMode = 1; /* Use output mode to determine separators */ - - failIfSafeMode(p, "cannot run .import in safe mode"); - memset(&sCtx, 0, sizeof(sCtx)); - sCtx.z = sqlite3_malloc64(120); - if( sCtx.z==0 ){ - import_cleanup(&sCtx); - shell_out_of_memory(); - } - if( p->mode==MODE_Ascii ){ - xRead = ascii_read_one_field; - }else{ - xRead = csv_read_one_field; - } - for(i=1; iout, "ERROR: extra argument: \"%s\". Usage:\n", z); - showHelp(p->out, "import"); - rc = 1; - goto meta_command_exit; - } - }else if( strcmp(z,"-v")==0 ){ - eVerbose++; - }else if( strcmp(z,"-skip")==0 && iout, "ERROR: unknown option: \"%s\". Usage:\n", z); - showHelp(p->out, "import"); - rc = 1; - goto meta_command_exit; - } - } - if( zTable==0 ){ - utf8_printf(p->out, "ERROR: missing %s argument. Usage:\n", - zFile==0 ? "FILE" : "TABLE"); - showHelp(p->out, "import"); - rc = 1; - goto meta_command_exit; - } - seenInterrupt = 0; - open_db(p, 0); - if( useOutputMode ){ - /* If neither the --csv or --ascii options are specified, then set + n2 = strlen30(zCmd); + for(i=0; idb, zSchema, SQLITE_FCNTL_SIZE_LIMIT, &iRes); + isOk = 1; + break; + } + case SQLITE_FCNTL_LOCK_TIMEOUT: + case SQLITE_FCNTL_CHUNK_SIZE: { + int x; + if( nArg!=3 ) break; + x = (int)integerValue(azArg[2]); + sqlite3_file_control(p->db, zSchema, filectrl, &x); + isOk = 2; + break; + } + case SQLITE_FCNTL_PERSIST_WAL: + case SQLITE_FCNTL_POWERSAFE_OVERWRITE: { + int x; + if( nArg!=2 && nArg!=3 ) break; + x = nArg==3 ? booleanValue(azArg[2]) : -1; + sqlite3_file_control(p->db, zSchema, filectrl, &x); + iRes = x; + isOk = 1; + break; + } + case SQLITE_FCNTL_DATA_VERSION: + case SQLITE_FCNTL_HAS_MOVED: { + int x; + if( nArg!=2 ) break; + sqlite3_file_control(p->db, zSchema, filectrl, &x); + iRes = x; + isOk = 1; + break; + } + case SQLITE_FCNTL_TEMPFILENAME: { + char *z = 0; + if( nArg!=2 ) break; + sqlite3_file_control(p->db, zSchema, filectrl, &z); + if( z ){ + utf8_printf(p->out, "%s\n", z); + sqlite3_free(z); + } + isOk = 2; + break; + } + case SQLITE_FCNTL_RESERVE_BYTES: { + int x; + if( nArg>=3 ){ + x = atoi(azArg[2]); + sqlite3_file_control(p->db, zSchema, filectrl, &x); + } + x = -1; + sqlite3_file_control(p->db, zSchema, filectrl, &x); + utf8_printf(p->out,"%d\n", x); + isOk = 2; + break; + } + } + } + if( isOk==0 && iCtrl>=0 ){ + utf8_printf(p->out, "Usage: .filectrl %s %s\n", zCmd,aCtrl[iCtrl].zUsage); + rc = 1; + }else if( isOk==1 ){ + char zBuf[100]; + sqlite3_snprintf(sizeof(zBuf), zBuf, "%lld", iRes); + raw_printf(p->out, "%s\n", zBuf); + } + }else + + if( c=='f' && strncmp(azArg[0], "fullschema", n)==0 ){ + ShellState data; + int doStats = 0; + memcpy(&data, p, sizeof(data)); + data.showHeader = 0; + data.cMode = data.mode = MODE_Semi; + if( nArg==2 && optionMatch(azArg[1], "indent") ){ + data.cMode = data.mode = MODE_Pretty; + nArg = 1; + } + if( nArg!=1 ){ + raw_printf(stderr, "Usage: .fullschema ?--indent?\n"); + rc = 1; + goto meta_command_exit; + } + open_db(p, 0); + rc = sqlite3_exec(p->db, + "SELECT sql FROM" + " (SELECT sql sql, type type, tbl_name tbl_name, name name, rowid x" + " FROM sqlite_schema UNION ALL" + " SELECT sql, type, tbl_name, name, rowid FROM sqlite_temp_schema) " + "WHERE type!='meta' AND sql NOTNULL AND name NOT LIKE 'sqlite_%' " + "ORDER BY x", + callback, &data, 0 + ); + if( rc==SQLITE_OK ){ + sqlite3_stmt *pStmt; + rc = sqlite3_prepare_v2(p->db, + "SELECT rowid FROM sqlite_schema" + " WHERE name GLOB 'sqlite_stat[134]'", + -1, &pStmt, 0); + doStats = sqlite3_step(pStmt)==SQLITE_ROW; + sqlite3_finalize(pStmt); + } + if( doStats==0 ){ + raw_printf(p->out, "/* No STAT tables available */\n"); + }else{ + raw_printf(p->out, "ANALYZE sqlite_schema;\n"); + data.cMode = data.mode = MODE_Insert; + data.zDestTable = "sqlite_stat1"; + shell_exec(&data, "SELECT * FROM sqlite_stat1", 0); + data.zDestTable = "sqlite_stat4"; + shell_exec(&data, "SELECT * FROM sqlite_stat4", 0); + raw_printf(p->out, "ANALYZE sqlite_schema;\n"); + } + }else + + if( c=='h' && strncmp(azArg[0], "headers", n)==0 ){ + if( nArg==2 ){ + p->showHeader = booleanValue(azArg[1]); + p->shellFlgs |= SHFLG_HeaderSet; + }else{ + raw_printf(stderr, "Usage: .headers on|off\n"); + rc = 1; + } + }else + + if( c=='h' && strncmp(azArg[0], "help", n)==0 ){ + if( nArg>=2 ){ + n = showHelp(p->out, azArg[1]); + if( n==0 ){ + utf8_printf(p->out, "Nothing matches '%s'\n", azArg[1]); + } + }else{ + showHelp(p->out, 0); + } + }else + + if( c=='i' && strncmp(azArg[0], "import", n)==0 ){ + char *zTable = 0; /* Insert data into this table */ + char *zFile = 0; /* Name of file to extra content from */ + sqlite3_stmt *pStmt = NULL; /* A statement */ + int nCol; /* Number of columns in the table */ + int nByte; /* Number of bytes in an SQL string */ + int i, j; /* Loop counters */ + int needCommit; /* True to COMMIT or ROLLBACK at end */ + int nSep; /* Number of bytes in p->colSeparator[] */ + char *zSql; /* An SQL statement */ + ImportCtx sCtx; /* Reader context */ + char *(SQLITE_CDECL *xRead)(ImportCtx*); /* Func to read one value */ + int eVerbose = 0; /* Larger for more console output */ + int nSkip = 0; /* Initial lines to skip */ + int useOutputMode = 1; /* Use output mode to determine separators */ + + failIfSafeMode(p, "cannot run .import in safe mode"); + memset(&sCtx, 0, sizeof(sCtx)); + sCtx.z = sqlite3_malloc64(120); + if( sCtx.z==0 ){ + import_cleanup(&sCtx); + shell_out_of_memory(); + } + if( p->mode==MODE_Ascii ){ + xRead = ascii_read_one_field; + }else{ + xRead = csv_read_one_field; + } + for(i=1; iout, "ERROR: extra argument: \"%s\". Usage:\n", z); + showHelp(p->out, "import"); + rc = 1; + goto meta_command_exit; + } + }else if( strcmp(z,"-v")==0 ){ + eVerbose++; + }else if( strcmp(z,"-skip")==0 && iout, "ERROR: unknown option: \"%s\". Usage:\n", z); + showHelp(p->out, "import"); + rc = 1; + goto meta_command_exit; + } + } + if( zTable==0 ){ + utf8_printf(p->out, "ERROR: missing %s argument. Usage:\n", + zFile==0 ? "FILE" : "TABLE"); + showHelp(p->out, "import"); + rc = 1; + goto meta_command_exit; + } + seenInterrupt = 0; + open_db(p, 0); + if( useOutputMode ){ + /* If neither the --csv or --ascii options are specified, then set ** the column and row separator characters from the output mode. */ - nSep = strlen30(p->colSeparator); - if( nSep==0 ){ - raw_printf(stderr, - "Error: non-null column separator required for import\n"); - rc = 1; - goto meta_command_exit; - } - if( nSep>1 ){ - raw_printf(stderr, - "Error: multi-character column separators not allowed" - " for import\n"); - rc = 1; - goto meta_command_exit; - } - nSep = strlen30(p->rowSeparator); - if( nSep==0 ){ - raw_printf(stderr, - "Error: non-null row separator required for import\n"); - rc = 1; - goto meta_command_exit; - } - if( nSep==2 && p->mode==MODE_Csv && strcmp(p->rowSeparator,SEP_CrLf)==0 ){ - /* When importing CSV (only), if the row separator is set to the + nSep = strlen30(p->colSeparator); + if( nSep==0 ){ + raw_printf(stderr, + "Error: non-null column separator required for import\n"); + rc = 1; + goto meta_command_exit; + } + if( nSep>1 ){ + raw_printf(stderr, + "Error: multi-character column separators not allowed" + " for import\n"); + rc = 1; + goto meta_command_exit; + } + nSep = strlen30(p->rowSeparator); + if( nSep==0 ){ + raw_printf(stderr, + "Error: non-null row separator required for import\n"); + rc = 1; + goto meta_command_exit; + } + if( nSep==2 && p->mode==MODE_Csv && strcmp(p->rowSeparator,SEP_CrLf)==0 ){ + /* When importing CSV (only), if the row separator is set to the ** default output row separator, change it to the default input ** row separator. This avoids having to maintain different input ** and output row separators. */ - sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row); - nSep = strlen30(p->rowSeparator); - } - if( nSep>1 ){ - raw_printf(stderr, "Error: multi-character row separators not allowed" - " for import\n"); - rc = 1; - goto meta_command_exit; - } - sCtx.cColSep = p->colSeparator[0]; - sCtx.cRowSep = p->rowSeparator[0]; - } - sCtx.zFile = zFile; - sCtx.nLine = 1; - if( sCtx.zFile[0]=='|' ){ + sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row); + nSep = strlen30(p->rowSeparator); + } + if( nSep>1 ){ + raw_printf(stderr, "Error: multi-character row separators not allowed" + " for import\n"); + rc = 1; + goto meta_command_exit; + } + sCtx.cColSep = p->colSeparator[0]; + sCtx.cRowSep = p->rowSeparator[0]; + } + sCtx.zFile = zFile; + sCtx.nLine = 1; + if( sCtx.zFile[0]=='|' ){ #ifdef SQLITE_OMIT_POPEN - raw_printf(stderr, "Error: pipes are not supported in this OS\n"); - rc = 1; - goto meta_command_exit; + raw_printf(stderr, "Error: pipes are not supported in this OS\n"); + rc = 1; + goto meta_command_exit; #else - sCtx.in = popen(sCtx.zFile+1, "r"); - sCtx.zFile = ""; - sCtx.xCloser = pclose; + sCtx.in = popen(sCtx.zFile+1, "r"); + sCtx.zFile = ""; + sCtx.xCloser = pclose; #endif - }else{ - sCtx.in = fopen(sCtx.zFile, "rb"); - sCtx.xCloser = fclose; - } - if( sCtx.in==0 ){ - utf8_printf(stderr, "Error: cannot open \"%s\"\n", zFile); - rc = 1; - import_cleanup(&sCtx); - goto meta_command_exit; - } - if( eVerbose>=2 || (eVerbose>=1 && useOutputMode) ){ - char zSep[2]; - zSep[1] = 0; - zSep[0] = sCtx.cColSep; - utf8_printf(p->out, "Column separator "); - output_c_string(p->out, zSep); - utf8_printf(p->out, ", row separator "); - zSep[0] = sCtx.cRowSep; - output_c_string(p->out, zSep); - utf8_printf(p->out, "\n"); - } - while( (nSkip--)>0 ){ - while( xRead(&sCtx) && sCtx.cTerm==sCtx.cColSep ){} - } - zSql = sqlite3_mprintf("SELECT * FROM \"%w\"", zTable); - if( zSql==0 ){ - import_cleanup(&sCtx); - shell_out_of_memory(); - } - nByte = strlen30(zSql); - rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); - import_append_char(&sCtx, 0); /* To ensure sCtx.z is allocated */ - if( rc && sqlite3_strglob("no such table: *", sqlite3_errmsg(p->db))==0 ){ - char *zCreate = sqlite3_mprintf("CREATE TABLE \"%w\"", zTable); - char cSep = '('; - while( xRead(&sCtx) ){ - zCreate = sqlite3_mprintf("%z%c\n \"%w\" TEXT", zCreate, cSep, sCtx.z); - cSep = ','; - if( sCtx.cTerm!=sCtx.cColSep ) break; - } - if( cSep=='(' ){ - sqlite3_free(zCreate); - import_cleanup(&sCtx); - utf8_printf(stderr,"%s: empty file\n", sCtx.zFile); - rc = 1; - goto meta_command_exit; - } - zCreate = sqlite3_mprintf("%z\n)", zCreate); - if( eVerbose>=1 ){ - utf8_printf(p->out, "%s\n", zCreate); - } - rc = sqlite3_exec(p->db, zCreate, 0, 0, 0); - sqlite3_free(zCreate); - if( rc ){ - utf8_printf(stderr, "CREATE TABLE \"%s\"(...) failed: %s\n", zTable, - sqlite3_errmsg(p->db)); - import_cleanup(&sCtx); - rc = 1; - goto meta_command_exit; - } - rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); - } - sqlite3_free(zSql); - if( rc ){ - if (pStmt) sqlite3_finalize(pStmt); - utf8_printf(stderr,"Error: %s\n", sqlite3_errmsg(p->db)); - import_cleanup(&sCtx); - rc = 1; - goto meta_command_exit; - } - nCol = sqlite3_column_count(pStmt); - sqlite3_finalize(pStmt); - pStmt = 0; - if( nCol==0 ) return 0; /* no columns, no error */ - zSql = sqlite3_malloc64( nByte*2 + 20 + nCol*2 ); - if( zSql==0 ){ - import_cleanup(&sCtx); - shell_out_of_memory(); - } - sqlite3_snprintf(nByte+20, zSql, "INSERT INTO \"%w\" VALUES(?", zTable); - j = strlen30(zSql); - for(i=1; i=2 ){ - utf8_printf(p->out, "Insert using: %s\n", zSql); - } - rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); - sqlite3_free(zSql); - if( rc ){ - utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db)); - if (pStmt) sqlite3_finalize(pStmt); - import_cleanup(&sCtx); - rc = 1; - goto meta_command_exit; - } - needCommit = sqlite3_get_autocommit(p->db); - if( needCommit ) sqlite3_exec(p->db, "BEGIN", 0, 0, 0); - do{ - int startLine = sCtx.nLine; - for(i=0; i=2 || (eVerbose>=1 && useOutputMode) ){ + char zSep[2]; + zSep[1] = 0; + zSep[0] = sCtx.cColSep; + utf8_printf(p->out, "Column separator "); + output_c_string(p->out, zSep); + utf8_printf(p->out, ", row separator "); + zSep[0] = sCtx.cRowSep; + output_c_string(p->out, zSep); + utf8_printf(p->out, "\n"); + } + while( (nSkip--)>0 ){ + while( xRead(&sCtx) && sCtx.cTerm==sCtx.cColSep ){} + } + zSql = sqlite3_mprintf("SELECT * FROM \"%w\"", zTable); + if( zSql==0 ){ + import_cleanup(&sCtx); + shell_out_of_memory(); + } + nByte = strlen30(zSql); + rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); + import_append_char(&sCtx, 0); /* To ensure sCtx.z is allocated */ + if( rc && sqlite3_strglob("no such table: *", sqlite3_errmsg(p->db))==0 ){ + char *zCreate = sqlite3_mprintf("CREATE TABLE \"%w\"", zTable); + char cSep = '('; + while( xRead(&sCtx) ){ + zCreate = sqlite3_mprintf("%z%c\n \"%w\" TEXT", zCreate, cSep, sCtx.z); + cSep = ','; + if( sCtx.cTerm!=sCtx.cColSep ) break; + } + if( cSep=='(' ){ + sqlite3_free(zCreate); + import_cleanup(&sCtx); + utf8_printf(stderr,"%s: empty file\n", sCtx.zFile); + rc = 1; + goto meta_command_exit; + } + zCreate = sqlite3_mprintf("%z\n)", zCreate); + if( eVerbose>=1 ){ + utf8_printf(p->out, "%s\n", zCreate); + } + rc = sqlite3_exec(p->db, zCreate, 0, 0, 0); + sqlite3_free(zCreate); + if( rc ){ + utf8_printf(stderr, "CREATE TABLE \"%s\"(...) failed: %s\n", zTable, + sqlite3_errmsg(p->db)); + import_cleanup(&sCtx); + rc = 1; + goto meta_command_exit; + } + rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); + } + sqlite3_free(zSql); + if( rc ){ + if (pStmt) sqlite3_finalize(pStmt); + utf8_printf(stderr,"Error: %s\n", sqlite3_errmsg(p->db)); + import_cleanup(&sCtx); + rc = 1; + goto meta_command_exit; + } + nCol = sqlite3_column_count(pStmt); + sqlite3_finalize(pStmt); + pStmt = 0; + if( nCol==0 ) return 0; /* no columns, no error */ + zSql = sqlite3_malloc64( nByte*2 + 20 + nCol*2 ); + if( zSql==0 ){ + import_cleanup(&sCtx); + shell_out_of_memory(); + } + sqlite3_snprintf(nByte+20, zSql, "INSERT INTO \"%w\" VALUES(?", zTable); + j = strlen30(zSql); + for(i=1; i=2 ){ + utf8_printf(p->out, "Insert using: %s\n", zSql); + } + rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); + sqlite3_free(zSql); + if( rc ){ + utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db)); + if (pStmt) sqlite3_finalize(pStmt); + import_cleanup(&sCtx); + rc = 1; + goto meta_command_exit; + } + needCommit = sqlite3_get_autocommit(p->db); + if( needCommit ) sqlite3_exec(p->db, "BEGIN", 0, 0, 0); + do{ + int startLine = sCtx.nLine; + for(i=0; imode==MODE_Ascii && (z==0 || z[0]==0) && i==0 ) break; - sqlite3_bind_text(pStmt, i+1, z, -1, SQLITE_TRANSIENT); - if( i=nCol ){ - sqlite3_step(pStmt); - rc = sqlite3_reset(pStmt); - if( rc!=SQLITE_OK ){ - utf8_printf(stderr, "%s:%d: INSERT failed: %s\n", sCtx.zFile, - startLine, sqlite3_errmsg(p->db)); - sCtx.nErr++; - }else{ - sCtx.nRow++; - } - } - }while( sCtx.cTerm!=EOF ); - - import_cleanup(&sCtx); - sqlite3_finalize(pStmt); - if( needCommit ) sqlite3_exec(p->db, "COMMIT", 0, 0, 0); - if( eVerbose>0 ){ - utf8_printf(p->out, - "Added %d rows with %d errors using %d lines of input\n", - sCtx.nRow, sCtx.nErr, sCtx.nLine-1); - } - }else + if( p->mode==MODE_Ascii && (z==0 || z[0]==0) && i==0 ) break; + sqlite3_bind_text(pStmt, i+1, z, -1, SQLITE_TRANSIENT); + if( i=nCol ){ + sqlite3_step(pStmt); + rc = sqlite3_reset(pStmt); + if( rc!=SQLITE_OK ){ + utf8_printf(stderr, "%s:%d: INSERT failed: %s\n", sCtx.zFile, + startLine, sqlite3_errmsg(p->db)); + sCtx.nErr++; + }else{ + sCtx.nRow++; + } + } + }while( sCtx.cTerm!=EOF ); + + import_cleanup(&sCtx); + sqlite3_finalize(pStmt); + if( needCommit ) sqlite3_exec(p->db, "COMMIT", 0, 0, 0); + if( eVerbose>0 ){ + utf8_printf(p->out, + "Added %d rows with %d errors using %d lines of input\n", + sCtx.nRow, sCtx.nErr, sCtx.nLine-1); + } + }else #ifndef SQLITE_UNTESTABLE - if( c=='i' && strncmp(azArg[0], "imposter", n)==0 ){ - char *zSql; - char *zCollist = 0; - sqlite3_stmt *pStmt; - int tnum = 0; - int isWO = 0; /* True if making an imposter of a WITHOUT ROWID table */ - int lenPK = 0; /* Length of the PRIMARY KEY string for isWO tables */ - int i; - if( !(nArg==3 || (nArg==2 && sqlite3_stricmp(azArg[1],"off")==0)) ){ - utf8_printf(stderr, "Usage: .imposter INDEX IMPOSTER\n" - " .imposter off\n"); - /* Also allowed, but not documented: + if( c=='i' && strncmp(azArg[0], "imposter", n)==0 ){ + char *zSql; + char *zCollist = 0; + sqlite3_stmt *pStmt; + int tnum = 0; + int isWO = 0; /* True if making an imposter of a WITHOUT ROWID table */ + int lenPK = 0; /* Length of the PRIMARY KEY string for isWO tables */ + int i; + if( !(nArg==3 || (nArg==2 && sqlite3_stricmp(azArg[1],"off")==0)) ){ + utf8_printf(stderr, "Usage: .imposter INDEX IMPOSTER\n" + " .imposter off\n"); + /* Also allowed, but not documented: ** ** .imposter TABLE IMPOSTER ** ** where TABLE is a WITHOUT ROWID table. In that case, the ** imposter is another WITHOUT ROWID table with the columns in ** storage order. */ - rc = 1; - goto meta_command_exit; - } - open_db(p, 0); - if( nArg==2 ){ - sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 0, 1); - goto meta_command_exit; - } - zSql = sqlite3_mprintf( - "SELECT rootpage, 0 FROM sqlite_schema" - " WHERE name='%q' AND type='index'" - "UNION ALL " - "SELECT rootpage, 1 FROM sqlite_schema" - " WHERE name='%q' AND type='table'" - " AND sql LIKE '%%without%%rowid%%'", - azArg[1], azArg[1] - ); - sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); - sqlite3_free(zSql); - if( sqlite3_step(pStmt)==SQLITE_ROW ){ - tnum = sqlite3_column_int(pStmt, 0); - isWO = sqlite3_column_int(pStmt, 1); - } - sqlite3_finalize(pStmt); - zSql = sqlite3_mprintf("PRAGMA index_xinfo='%q'", azArg[1]); - rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); - sqlite3_free(zSql); - i = 0; - while( rc==SQLITE_OK && sqlite3_step(pStmt)==SQLITE_ROW ){ - char zLabel[20]; - const char *zCol = (const char*)sqlite3_column_text(pStmt,2); - i++; - if( zCol==0 ){ - if( sqlite3_column_int(pStmt,1)==-1 ){ - zCol = "_ROWID_"; - }else{ - sqlite3_snprintf(sizeof(zLabel),zLabel,"expr%d",i); - zCol = zLabel; - } - } - if( isWO && lenPK==0 && sqlite3_column_int(pStmt,5)==0 && zCollist ){ - lenPK = (int)strlen(zCollist); - } - if( zCollist==0 ){ - zCollist = sqlite3_mprintf("\"%w\"", zCol); - }else{ - zCollist = sqlite3_mprintf("%z,\"%w\"", zCollist, zCol); - } - } - sqlite3_finalize(pStmt); - if( i==0 || tnum==0 ){ - utf8_printf(stderr, "no such index: \"%s\"\n", azArg[1]); - rc = 1; - sqlite3_free(zCollist); - goto meta_command_exit; - } - if( lenPK==0 ) lenPK = 100000; - zSql = sqlite3_mprintf( - "CREATE TABLE \"%w\"(%s,PRIMARY KEY(%.*s))WITHOUT ROWID", - azArg[2], zCollist, lenPK, zCollist); - sqlite3_free(zCollist); - rc = sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 1, tnum); - if( rc==SQLITE_OK ){ - rc = sqlite3_exec(p->db, zSql, 0, 0, 0); - sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 0, 0); - if( rc ){ - utf8_printf(stderr, "Error in [%s]: %s\n", zSql, sqlite3_errmsg(p->db)); - }else{ - utf8_printf(stdout, "%s;\n", zSql); - raw_printf(stdout, - "WARNING: writing to an imposter table will corrupt the \"%s\" %s!\n", - azArg[1], isWO ? "table" : "index" - ); - } - }else{ - raw_printf(stderr, "SQLITE_TESTCTRL_IMPOSTER returns %d\n", rc); - rc = 1; - } - sqlite3_free(zSql); - }else + rc = 1; + goto meta_command_exit; + } + open_db(p, 0); + if( nArg==2 ){ + sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 0, 1); + goto meta_command_exit; + } + zSql = sqlite3_mprintf( + "SELECT rootpage, 0 FROM sqlite_schema" + " WHERE name='%q' AND type='index'" + "UNION ALL " + "SELECT rootpage, 1 FROM sqlite_schema" + " WHERE name='%q' AND type='table'" + " AND sql LIKE '%%without%%rowid%%'", + azArg[1], azArg[1] + ); + sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); + sqlite3_free(zSql); + if( sqlite3_step(pStmt)==SQLITE_ROW ){ + tnum = sqlite3_column_int(pStmt, 0); + isWO = sqlite3_column_int(pStmt, 1); + } + sqlite3_finalize(pStmt); + zSql = sqlite3_mprintf("PRAGMA index_xinfo='%q'", azArg[1]); + rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); + sqlite3_free(zSql); + i = 0; + while( rc==SQLITE_OK && sqlite3_step(pStmt)==SQLITE_ROW ){ + char zLabel[20]; + const char *zCol = (const char*)sqlite3_column_text(pStmt,2); + i++; + if( zCol==0 ){ + if( sqlite3_column_int(pStmt,1)==-1 ){ + zCol = "_ROWID_"; + }else{ + sqlite3_snprintf(sizeof(zLabel),zLabel,"expr%d",i); + zCol = zLabel; + } + } + if( isWO && lenPK==0 && sqlite3_column_int(pStmt,5)==0 && zCollist ){ + lenPK = (int)strlen(zCollist); + } + if( zCollist==0 ){ + zCollist = sqlite3_mprintf("\"%w\"", zCol); + }else{ + zCollist = sqlite3_mprintf("%z,\"%w\"", zCollist, zCol); + } + } + sqlite3_finalize(pStmt); + if( i==0 || tnum==0 ){ + utf8_printf(stderr, "no such index: \"%s\"\n", azArg[1]); + rc = 1; + sqlite3_free(zCollist); + goto meta_command_exit; + } + if( lenPK==0 ) lenPK = 100000; + zSql = sqlite3_mprintf( + "CREATE TABLE \"%w\"(%s,PRIMARY KEY(%.*s))WITHOUT ROWID", + azArg[2], zCollist, lenPK, zCollist); + sqlite3_free(zCollist); + rc = sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 1, tnum); + if( rc==SQLITE_OK ){ + rc = sqlite3_exec(p->db, zSql, 0, 0, 0); + sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 0, 0); + if( rc ){ + utf8_printf(stderr, "Error in [%s]: %s\n", zSql, sqlite3_errmsg(p->db)); + }else{ + utf8_printf(stdout, "%s;\n", zSql); + raw_printf(stdout, + "WARNING: writing to an imposter table will corrupt the \"%s\" %s!\n", + azArg[1], isWO ? "table" : "index" + ); + } + }else{ + raw_printf(stderr, "SQLITE_TESTCTRL_IMPOSTER returns %d\n", rc); + rc = 1; + } + sqlite3_free(zSql); + }else #endif /* !defined(SQLITE_OMIT_TEST_CONTROL) */ #ifdef SQLITE_ENABLE_IOTRACE - if( c=='i' && strncmp(azArg[0], "iotrace", n)==0 ){ - SQLITE_API extern void (SQLITE_CDECL *sqlite3IoTrace)(const char*, ...); - if( iotrace && iotrace!=stdout ) fclose(iotrace); - iotrace = 0; - if( nArg<2 ){ - sqlite3IoTrace = 0; - }else if( strcmp(azArg[1], "-")==0 ){ - sqlite3IoTrace = iotracePrintf; - iotrace = stdout; - }else{ - iotrace = fopen(azArg[1], "w"); - if( iotrace==0 ){ - utf8_printf(stderr, "Error: cannot open \"%s\"\n", azArg[1]); - sqlite3IoTrace = 0; - rc = 1; - }else{ - sqlite3IoTrace = iotracePrintf; - } - } - }else + if( c=='i' && strncmp(azArg[0], "iotrace", n)==0 ){ + SQLITE_API extern void (SQLITE_CDECL *sqlite3IoTrace)(const char*, ...); + if( iotrace && iotrace!=stdout ) fclose(iotrace); + iotrace = 0; + if( nArg<2 ){ + sqlite3IoTrace = 0; + }else if( strcmp(azArg[1], "-")==0 ){ + sqlite3IoTrace = iotracePrintf; + iotrace = stdout; + }else{ + iotrace = fopen(azArg[1], "w"); + if( iotrace==0 ){ + utf8_printf(stderr, "Error: cannot open \"%s\"\n", azArg[1]); + sqlite3IoTrace = 0; + rc = 1; + }else{ + sqlite3IoTrace = iotracePrintf; + } + } + }else #endif - if( c=='l' && n>=5 && strncmp(azArg[0], "limits", n)==0 ){ - static const struct { - const char *zLimitName; /* Name of a limit */ - int limitCode; /* Integer code for that limit */ - } aLimit[] = { - { "length", SQLITE_LIMIT_LENGTH }, - { "sql_length", SQLITE_LIMIT_SQL_LENGTH }, - { "column", SQLITE_LIMIT_COLUMN }, - { "expr_depth", SQLITE_LIMIT_EXPR_DEPTH }, - { "compound_select", SQLITE_LIMIT_COMPOUND_SELECT }, - { "vdbe_op", SQLITE_LIMIT_VDBE_OP }, - { "function_arg", SQLITE_LIMIT_FUNCTION_ARG }, - { "attached", SQLITE_LIMIT_ATTACHED }, - { "like_pattern_length", SQLITE_LIMIT_LIKE_PATTERN_LENGTH }, - { "variable_number", SQLITE_LIMIT_VARIABLE_NUMBER }, - { "trigger_depth", SQLITE_LIMIT_TRIGGER_DEPTH }, - { "worker_threads", SQLITE_LIMIT_WORKER_THREADS }, - }; - int i, n2; - open_db(p, 0); - if( nArg==1 ){ - for(i=0; idb, aLimit[i].limitCode, -1)); - } - }else if( nArg>3 ){ - raw_printf(stderr, "Usage: .limit NAME ?NEW-VALUE?\n"); - rc = 1; - goto meta_command_exit; - }else{ - int iLimit = -1; - n2 = strlen30(azArg[1]); - for(i=0; idb, aLimit[iLimit].limitCode, - (int)integerValue(azArg[2])); - } - printf("%20s %d\n", aLimit[iLimit].zLimitName, - sqlite3_limit(p->db, aLimit[iLimit].limitCode, -1)); - } - }else - - if( c=='l' && n>2 && strncmp(azArg[0], "lint", n)==0 ){ - open_db(p, 0); - lintDotCommand(p, azArg, nArg); - }else + if( c=='l' && n>=5 && strncmp(azArg[0], "limits", n)==0 ){ + static const struct { + const char *zLimitName; /* Name of a limit */ + int limitCode; /* Integer code for that limit */ + } aLimit[] = { + { "length", SQLITE_LIMIT_LENGTH }, + { "sql_length", SQLITE_LIMIT_SQL_LENGTH }, + { "column", SQLITE_LIMIT_COLUMN }, + { "expr_depth", SQLITE_LIMIT_EXPR_DEPTH }, + { "compound_select", SQLITE_LIMIT_COMPOUND_SELECT }, + { "vdbe_op", SQLITE_LIMIT_VDBE_OP }, + { "function_arg", SQLITE_LIMIT_FUNCTION_ARG }, + { "attached", SQLITE_LIMIT_ATTACHED }, + { "like_pattern_length", SQLITE_LIMIT_LIKE_PATTERN_LENGTH }, + { "variable_number", SQLITE_LIMIT_VARIABLE_NUMBER }, + { "trigger_depth", SQLITE_LIMIT_TRIGGER_DEPTH }, + { "worker_threads", SQLITE_LIMIT_WORKER_THREADS }, + }; + int i, n2; + open_db(p, 0); + if( nArg==1 ){ + for(i=0; idb, aLimit[i].limitCode, -1)); + } + }else if( nArg>3 ){ + raw_printf(stderr, "Usage: .limit NAME ?NEW-VALUE?\n"); + rc = 1; + goto meta_command_exit; + }else{ + int iLimit = -1; + n2 = strlen30(azArg[1]); + for(i=0; idb, aLimit[iLimit].limitCode, + (int)integerValue(azArg[2])); + } + printf("%20s %d\n", aLimit[iLimit].zLimitName, + sqlite3_limit(p->db, aLimit[iLimit].limitCode, -1)); + } + }else + + if( c=='l' && n>2 && strncmp(azArg[0], "lint", n)==0 ){ + open_db(p, 0); + lintDotCommand(p, azArg, nArg); + }else #ifndef SQLITE_OMIT_LOAD_EXTENSION - if( c=='l' && strncmp(azArg[0], "load", n)==0 ){ - const char *zFile, *zProc; - char *zErrMsg = 0; - failIfSafeMode(p, "cannot run .load in safe mode"); - if( nArg<2 ){ - raw_printf(stderr, "Usage: .load FILE ?ENTRYPOINT?\n"); - rc = 1; - goto meta_command_exit; - } - zFile = azArg[1]; - zProc = nArg>=3 ? azArg[2] : 0; - open_db(p, 0); - rc = sqlite3_load_extension(p->db, zFile, zProc, &zErrMsg); - if( rc!=SQLITE_OK ){ - utf8_printf(stderr, "Error: %s\n", zErrMsg); - sqlite3_free(zErrMsg); - rc = 1; - } - }else + if( c=='l' && strncmp(azArg[0], "load", n)==0 ){ + const char *zFile, *zProc; + char *zErrMsg = 0; + failIfSafeMode(p, "cannot run .load in safe mode"); + if( nArg<2 ){ + raw_printf(stderr, "Usage: .load FILE ?ENTRYPOINT?\n"); + rc = 1; + goto meta_command_exit; + } + zFile = azArg[1]; + zProc = nArg>=3 ? azArg[2] : 0; + open_db(p, 0); + rc = sqlite3_load_extension(p->db, zFile, zProc, &zErrMsg); + if( rc!=SQLITE_OK ){ + utf8_printf(stderr, "Error: %s\n", zErrMsg); + sqlite3_free(zErrMsg); + rc = 1; + } + }else #endif - if( c=='l' && strncmp(azArg[0], "log", n)==0 ){ - failIfSafeMode(p, "cannot run .log in safe mode"); - if( nArg!=2 ){ - raw_printf(stderr, "Usage: .log FILENAME\n"); - rc = 1; - }else{ - const char *zFile = azArg[1]; - output_file_close(p->pLog); - p->pLog = output_file_open(zFile, 0); - } - }else - - if( c=='m' && strncmp(azArg[0], "mode", n)==0 ){ - const char *zMode = nArg>=2 ? azArg[1] : ""; - int n2 = strlen30(zMode); - int c2 = zMode[0]; - if( c2=='l' && n2>2 && strncmp(azArg[1],"lines",n2)==0 ){ - p->mode = MODE_Line; - sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row); - }else if( c2=='c' && strncmp(azArg[1],"columns",n2)==0 ){ - p->mode = MODE_Column; - if( (p->shellFlgs & SHFLG_HeaderSet)==0 ){ - p->showHeader = 1; - } - sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row); - }else if( c2=='l' && n2>2 && strncmp(azArg[1],"list",n2)==0 ){ - p->mode = MODE_List; - sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Column); - sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row); - }else if( c2=='h' && strncmp(azArg[1],"html",n2)==0 ){ - p->mode = MODE_Html; - }else if( c2=='t' && strncmp(azArg[1],"tcl",n2)==0 ){ - p->mode = MODE_Tcl; - sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Space); - sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row); - }else if( c2=='c' && strncmp(azArg[1],"csv",n2)==0 ){ - p->mode = MODE_Csv; - sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Comma); - sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_CrLf); - }else if( c2=='t' && strncmp(azArg[1],"tabs",n2)==0 ){ - p->mode = MODE_List; - sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Tab); - }else if( c2=='i' && strncmp(azArg[1],"insert",n2)==0 ){ - p->mode = MODE_Insert; - set_table_name(p, nArg>=3 ? azArg[2] : "table"); - }else if( c2=='q' && strncmp(azArg[1],"quote",n2)==0 ){ - p->mode = MODE_Quote; - sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Comma); - sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row); - }else if( c2=='a' && strncmp(azArg[1],"ascii",n2)==0 ){ - p->mode = MODE_Ascii; - sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Unit); - sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Record); - }else if( c2=='m' && strncmp(azArg[1],"markdown",n2)==0 ){ - p->mode = MODE_Markdown; - }else if( c2=='t' && strncmp(azArg[1],"table",n2)==0 ){ - p->mode = MODE_Table; - }else if( c2=='b' && strncmp(azArg[1],"box",n2)==0 ){ - p->mode = MODE_Box; - }else if( c2=='j' && strncmp(azArg[1],"json",n2)==0 ){ - p->mode = MODE_Json; - }else if( nArg==1 ){ - raw_printf(p->out, "current output mode: %s\n", modeDescr[p->mode]); - }else{ - raw_printf(stderr, "Error: mode should be one of: " - "ascii box column csv html insert json line list markdown " - "quote table tabs tcl\n"); - rc = 1; - } - p->cMode = p->mode; - }else - - if( c=='n' && strcmp(azArg[0], "nonce")==0 ){ - if( nArg!=2 ){ - raw_printf(stderr, "Usage: .nonce NONCE\n"); - rc = 1; - }else if( p->zNonce==0 || strcmp(azArg[1],p->zNonce)!=0 ){ - raw_printf(stderr, "line %d: incorrect nonce: \"%s\"\n", p->lineno, azArg[1]); - exit(1); - }else{ - p->bSafeMode = 0; - return 0; /* Return immediately to bypass the safe mode reset + if( c=='l' && strncmp(azArg[0], "log", n)==0 ){ + failIfSafeMode(p, "cannot run .log in safe mode"); + if( nArg!=2 ){ + raw_printf(stderr, "Usage: .log FILENAME\n"); + rc = 1; + }else{ + const char *zFile = azArg[1]; + output_file_close(p->pLog); + p->pLog = output_file_open(zFile, 0); + } + }else + + if( c=='m' && strncmp(azArg[0], "mode", n)==0 ){ + const char *zMode = nArg>=2 ? azArg[1] : ""; + int n2 = strlen30(zMode); + int c2 = zMode[0]; + if( c2=='l' && n2>2 && strncmp(azArg[1],"lines",n2)==0 ){ + p->mode = MODE_Line; + sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row); + }else if( c2=='c' && strncmp(azArg[1],"columns",n2)==0 ){ + p->mode = MODE_Column; + if( (p->shellFlgs & SHFLG_HeaderSet)==0 ){ + p->showHeader = 1; + } + sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row); + }else if( c2=='l' && n2>2 && strncmp(azArg[1],"list",n2)==0 ){ + p->mode = MODE_List; + sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Column); + sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row); + }else if( c2=='h' && strncmp(azArg[1],"html",n2)==0 ){ + p->mode = MODE_Html; + }else if( c2=='t' && strncmp(azArg[1],"tcl",n2)==0 ){ + p->mode = MODE_Tcl; + sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Space); + sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row); + }else if( c2=='c' && strncmp(azArg[1],"csv",n2)==0 ){ + p->mode = MODE_Csv; + sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Comma); + sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_CrLf); + }else if( c2=='t' && strncmp(azArg[1],"tabs",n2)==0 ){ + p->mode = MODE_List; + sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Tab); + }else if( c2=='i' && strncmp(azArg[1],"insert",n2)==0 ){ + p->mode = MODE_Insert; + set_table_name(p, nArg>=3 ? azArg[2] : "table"); + }else if( c2=='q' && strncmp(azArg[1],"quote",n2)==0 ){ + p->mode = MODE_Quote; + sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Comma); + sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row); + }else if( c2=='a' && strncmp(azArg[1],"ascii",n2)==0 ){ + p->mode = MODE_Ascii; + sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Unit); + sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Record); + }else if( c2=='m' && strncmp(azArg[1],"markdown",n2)==0 ){ + p->mode = MODE_Markdown; + }else if( c2=='t' && strncmp(azArg[1],"table",n2)==0 ){ + p->mode = MODE_Table; + }else if( c2=='b' && strncmp(azArg[1],"box",n2)==0 ){ + p->mode = MODE_Box; + }else if( c2=='j' && strncmp(azArg[1],"json",n2)==0 ){ + p->mode = MODE_Json; + }else if( nArg==1 ){ + raw_printf(p->out, "current output mode: %s\n", modeDescr[p->mode]); + }else{ + raw_printf(stderr, "Error: mode should be one of: " + "ascii box column csv html insert json line list markdown " + "quote table tabs tcl\n"); + rc = 1; + } + p->cMode = p->mode; + }else + + if( c=='n' && strcmp(azArg[0], "nonce")==0 ){ + if( nArg!=2 ){ + raw_printf(stderr, "Usage: .nonce NONCE\n"); + rc = 1; + }else if( p->zNonce==0 || strcmp(azArg[1],p->zNonce)!=0 ){ + raw_printf(stderr, "line %d: incorrect nonce: \"%s\"\n", p->lineno, azArg[1]); + exit(1); + }else{ + p->bSafeMode = 0; + return 0; /* Return immediately to bypass the safe mode reset ** at the end of this procedure */ - } - }else - - if( c=='n' && strncmp(azArg[0], "nullvalue", n)==0 ){ - if( nArg==2 ){ - sqlite3_snprintf(sizeof(p->nullValue), p->nullValue, - "%.*s", (int)ArraySize(p->nullValue)-1, azArg[1]); - }else{ - raw_printf(stderr, "Usage: .nullvalue STRING\n"); - rc = 1; - } - }else + } + }else + + if( c=='n' && strncmp(azArg[0], "nullvalue", n)==0 ){ + if( nArg==2 ){ + sqlite3_snprintf(sizeof(p->nullValue), p->nullValue, + "%.*s", (int)ArraySize(p->nullValue)-1, azArg[1]); + }else{ + raw_printf(stderr, "Usage: .nullvalue STRING\n"); + rc = 1; + } + }else #ifdef SQLITE_DEBUG - if( c=='o' && strcmp(azArg[0],"oom")==0 ){ - int i; - for(i=1; iout, "missing argument on \"%s\"\n", azArg[i]); - rc = 1; - }else{ - oomRepeat = (int)integerValue(azArg[++i]); - } - }else if( IsDigit(z[0]) ){ - oomCounter = (int)integerValue(azArg[i]); - }else{ - raw_printf(p->out, "unknown argument: \"%s\"\n", azArg[i]); - raw_printf(p->out, "Usage: .oom [--repeat N] [M]\n"); - rc = 1; - } - } - if( rc==0 ){ - raw_printf(p->out, "oomCounter = %d\n", oomCounter); - raw_printf(p->out, "oomRepeat = %d\n", oomRepeat); - } - }else + if( c=='o' && strcmp(azArg[0],"oom")==0 ){ + int i; + for(i=1; iout, "missing argument on \"%s\"\n", azArg[i]); + rc = 1; + }else{ + oomRepeat = (int)integerValue(azArg[++i]); + } + }else if( IsDigit(z[0]) ){ + oomCounter = (int)integerValue(azArg[i]); + }else{ + raw_printf(p->out, "unknown argument: \"%s\"\n", azArg[i]); + raw_printf(p->out, "Usage: .oom [--repeat N] [M]\n"); + rc = 1; + } + } + if( rc==0 ){ + raw_printf(p->out, "oomCounter = %d\n", oomCounter); + raw_printf(p->out, "oomRepeat = %d\n", oomRepeat); + } + }else #endif /* SQLITE_DEBUG */ - if( c=='o' && strncmp(azArg[0], "open", n)==0 && n>=2 ){ - char *zNewFilename = 0; /* Name of the database file to open */ - int iName = 1; /* Index in azArg[] of the filename */ - int newFlag = 0; /* True to delete file before opening */ - int openMode = SHELL_OPEN_UNSPEC; - - /* Check for command-line arguments */ - for(iName=1; iName=2 ){ + char *zNewFilename = 0; /* Name of the database file to open */ + int iName = 1; /* Index in azArg[] of the filename */ + int newFlag = 0; /* True to delete file before opening */ + int openMode = SHELL_OPEN_UNSPEC; + + /* Check for command-line arguments */ + for(iName=1; iNameopenFlags |= SQLITE_OPEN_NOFOLLOW; + }else if( optionMatch(z, "append") ){ + openMode = SHELL_OPEN_APPENDVFS; + }else if( optionMatch(z, "readonly") ){ + openMode = SHELL_OPEN_READONLY; + }else if( optionMatch(z, "nofollow") ){ + p->openFlags |= SQLITE_OPEN_NOFOLLOW; #ifndef SQLITE_OMIT_DESERIALIZE - }else if( optionMatch(z, "deserialize") ){ - openMode = SHELL_OPEN_DESERIALIZE; - }else if( optionMatch(z, "hexdb") ){ - openMode = SHELL_OPEN_HEXDB; - }else if( optionMatch(z, "maxsize") && iName+1szMax = integerValue(azArg[++iName]); + }else if( optionMatch(z, "deserialize") ){ + openMode = SHELL_OPEN_DESERIALIZE; + }else if( optionMatch(z, "hexdb") ){ + openMode = SHELL_OPEN_HEXDB; + }else if( optionMatch(z, "maxsize") && iName+1szMax = integerValue(azArg[++iName]); #endif /* SQLITE_OMIT_DESERIALIZE */ - }else if( z[0]=='-' ){ - utf8_printf(stderr, "unknown option: %s\n", z); - rc = 1; - goto meta_command_exit; - }else if( zNewFilename ){ - utf8_printf(stderr, "extra argument: \"%s\"\n", z); - rc = 1; - goto meta_command_exit; - }else{ - zNewFilename = sqlite3_mprintf("%s", z); - } - } - - /* Close the existing database */ - session_close_all(p, -1); - close_db(p->db); - p->db = 0; - p->pAuxDb->zDbFilename = 0; - sqlite3_free(p->pAuxDb->zFreeOnClose); - p->pAuxDb->zFreeOnClose = 0; - p->openMode = openMode; - p->openFlags = 0; - p->szMax = 0; - - /* If a filename is specified, try to open it first */ - if( zNewFilename || p->openMode==SHELL_OPEN_HEXDB ){ - if( newFlag && !p->bSafeMode ) shellDeleteFile(zNewFilename); - if( p->bSafeMode - && p->openMode!=SHELL_OPEN_HEXDB - && zNewFilename - && strcmp(zNewFilename,":memory:")!=0 - ){ - failIfSafeMode(p, "cannot open disk-based database files in safe mode"); - } - p->pAuxDb->zDbFilename = zNewFilename; - open_db(p, OPEN_DB_KEEPALIVE); - if( p->db==0 ){ - utf8_printf(stderr, "Error: cannot open '%s'\n", zNewFilename); - sqlite3_free(zNewFilename); - }else{ - p->pAuxDb->zFreeOnClose = zNewFilename; - } - } - if( p->db==0 ){ - /* As a fall-back open a TEMP database */ - p->pAuxDb->zDbFilename = 0; - open_db(p, 0); - } - }else - - if( (c=='o' - && (strncmp(azArg[0], "output", n)==0||strncmp(azArg[0], "once", n)==0)) - || (c=='e' && n==5 && strcmp(azArg[0],"excel")==0) - ){ - char *zFile = 0; - int bTxtMode = 0; - int i; - int eMode = 0; - int bBOM = 0; - int bOnce = 0; /* 0: .output, 1: .once, 2: .excel */ - - failIfSafeMode(p, "cannot run .%s in safe mode", azArg[0]); - if( c=='e' ){ - eMode = 'x'; - bOnce = 2; - }else if( strncmp(azArg[0],"once",n)==0 ){ - bOnce = 1; - } - for(i=1; iout, "ERROR: unknown option: \"%s\". Usage:\n", - azArg[i]); - showHelp(p->out, azArg[0]); - rc = 1; - goto meta_command_exit; - } - }else if( zFile==0 && eMode!='e' && eMode!='x' ){ - zFile = sqlite3_mprintf("%s", z); - if( zFile[0]=='|' ){ - while( i+1out,"ERROR: extra parameter: \"%s\". Usage:\n", - azArg[i]); - showHelp(p->out, azArg[0]); - rc = 1; - sqlite3_free(zFile); - goto meta_command_exit; - } - } - if( zFile==0 ) zFile = sqlite3_mprintf("stdout"); - if( bOnce ){ - p->outCount = 2; - }else{ - p->outCount = 0; - } - output_reset(p); + }else if( z[0]=='-' ){ + utf8_printf(stderr, "unknown option: %s\n", z); + rc = 1; + goto meta_command_exit; + }else if( zNewFilename ){ + utf8_printf(stderr, "extra argument: \"%s\"\n", z); + rc = 1; + goto meta_command_exit; + }else{ + zNewFilename = sqlite3_mprintf("%s", z); + } + } + + /* Close the existing database */ + session_close_all(p, -1); + close_db(p->db); + p->db = 0; + p->pAuxDb->zDbFilename = 0; + sqlite3_free(p->pAuxDb->zFreeOnClose); + p->pAuxDb->zFreeOnClose = 0; + p->openMode = openMode; + p->openFlags = 0; + p->szMax = 0; + + /* If a filename is specified, try to open it first */ + if( zNewFilename || p->openMode==SHELL_OPEN_HEXDB ){ + if( newFlag && !p->bSafeMode ) shellDeleteFile(zNewFilename); + if( p->bSafeMode + && p->openMode!=SHELL_OPEN_HEXDB + && zNewFilename + && strcmp(zNewFilename,":memory:")!=0 + ){ + failIfSafeMode(p, "cannot open disk-based database files in safe mode"); + } + p->pAuxDb->zDbFilename = zNewFilename; + open_db(p, OPEN_DB_KEEPALIVE); + if( p->db==0 ){ + utf8_printf(stderr, "Error: cannot open '%s'\n", zNewFilename); + sqlite3_free(zNewFilename); + }else{ + p->pAuxDb->zFreeOnClose = zNewFilename; + } + } + if( p->db==0 ){ + /* As a fall-back open a TEMP database */ + p->pAuxDb->zDbFilename = 0; + open_db(p, 0); + } + }else + + if( (c=='o' + && (strncmp(azArg[0], "output", n)==0||strncmp(azArg[0], "once", n)==0)) + || (c=='e' && n==5 && strcmp(azArg[0],"excel")==0) + ){ + char *zFile = 0; + int bTxtMode = 0; + int i; + int eMode = 0; + int bBOM = 0; + int bOnce = 0; /* 0: .output, 1: .once, 2: .excel */ + + failIfSafeMode(p, "cannot run .%s in safe mode", azArg[0]); + if( c=='e' ){ + eMode = 'x'; + bOnce = 2; + }else if( strncmp(azArg[0],"once",n)==0 ){ + bOnce = 1; + } + for(i=1; iout, "ERROR: unknown option: \"%s\". Usage:\n", + azArg[i]); + showHelp(p->out, azArg[0]); + rc = 1; + goto meta_command_exit; + } + }else if( zFile==0 && eMode!='e' && eMode!='x' ){ + zFile = sqlite3_mprintf("%s", z); + if( zFile[0]=='|' ){ + while( i+1out,"ERROR: extra parameter: \"%s\". Usage:\n", + azArg[i]); + showHelp(p->out, azArg[0]); + rc = 1; + sqlite3_free(zFile); + goto meta_command_exit; + } + } + if( zFile==0 ) zFile = sqlite3_mprintf("stdout"); + if( bOnce ){ + p->outCount = 2; + }else{ + p->outCount = 0; + } + output_reset(p); #ifndef SQLITE_NOHAVE_SYSTEM - if( eMode=='e' || eMode=='x' ){ - p->doXdgOpen = 1; - outputModePush(p); - if( eMode=='x' ){ - /* spreadsheet mode. Output as CSV. */ - newTempFile(p, "csv"); - ShellClearFlag(p, SHFLG_Echo); - p->mode = MODE_Csv; - sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Comma); - sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_CrLf); - }else{ - /* text editor mode */ - newTempFile(p, "txt"); - bTxtMode = 1; - } - sqlite3_free(zFile); - zFile = sqlite3_mprintf("%s", p->zTempFile); - } + if( eMode=='e' || eMode=='x' ){ + p->doXdgOpen = 1; + outputModePush(p); + if( eMode=='x' ){ + /* spreadsheet mode. Output as CSV. */ + newTempFile(p, "csv"); + ShellClearFlag(p, SHFLG_Echo); + p->mode = MODE_Csv; + sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Comma); + sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_CrLf); + }else{ + /* text editor mode */ + newTempFile(p, "txt"); + bTxtMode = 1; + } + sqlite3_free(zFile); + zFile = sqlite3_mprintf("%s", p->zTempFile); + } #endif /* SQLITE_NOHAVE_SYSTEM */ - if( zFile[0]=='|' ){ + if( zFile[0]=='|' ){ #ifdef SQLITE_OMIT_POPEN - raw_printf(stderr, "Error: pipes are not supported in this OS\n"); - rc = 1; - p->out = stdout; + raw_printf(stderr, "Error: pipes are not supported in this OS\n"); + rc = 1; + p->out = stdout; #else - p->out = popen(zFile + 1, "w"); - if( p->out==0 ){ - utf8_printf(stderr,"Error: cannot open pipe \"%s\"\n", zFile + 1); - p->out = stdout; - rc = 1; - }else{ - if( bBOM ) fprintf(p->out,"\357\273\277"); - sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", zFile); - } + p->out = popen(zFile + 1, "w"); + if( p->out==0 ){ + utf8_printf(stderr,"Error: cannot open pipe \"%s\"\n", zFile + 1); + p->out = stdout; + rc = 1; + }else{ + if( bBOM ) fprintf(p->out,"\357\273\277"); + sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", zFile); + } #endif - }else{ - p->out = output_file_open(zFile, bTxtMode); - if( p->out==0 ){ - if( strcmp(zFile,"off")!=0 ){ - utf8_printf(stderr,"Error: cannot write to \"%s\"\n", zFile); - } - p->out = stdout; - rc = 1; - } else { - if( bBOM ) fprintf(p->out,"\357\273\277"); - sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", zFile); - } - } - sqlite3_free(zFile); - }else - - if( c=='p' && n>=3 && strncmp(azArg[0], "parameter", n)==0 ){ - open_db(p,0); - if( nArg<=1 ) goto parameter_syntax_error; - - /* .parameter clear + }else{ + p->out = output_file_open(zFile, bTxtMode); + if( p->out==0 ){ + if( strcmp(zFile,"off")!=0 ){ + utf8_printf(stderr,"Error: cannot write to \"%s\"\n", zFile); + } + p->out = stdout; + rc = 1; + } else { + if( bBOM ) fprintf(p->out,"\357\273\277"); + sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", zFile); + } + } + sqlite3_free(zFile); + }else + + if( c=='p' && n>=3 && strncmp(azArg[0], "parameter", n)==0 ){ + open_db(p,0); + if( nArg<=1 ) goto parameter_syntax_error; + + /* .parameter clear ** Clear all bind parameters by dropping the TEMP table that holds them. */ - if( nArg==2 && strcmp(azArg[1],"clear")==0 ){ - sqlite3_exec(p->db, "DROP TABLE IF EXISTS temp.sqlite_parameters;", - 0, 0, 0); - }else + if( nArg==2 && strcmp(azArg[1],"clear")==0 ){ + sqlite3_exec(p->db, "DROP TABLE IF EXISTS temp.sqlite_parameters;", + 0, 0, 0); + }else - /* .parameter list + /* .parameter list ** List all bind parameters. */ - if( nArg==2 && strcmp(azArg[1],"list")==0 ){ - sqlite3_stmt *pStmt = 0; - int rx; - int len = 0; - rx = sqlite3_prepare_v2(p->db, - "SELECT max(length(key)) " - "FROM temp.sqlite_parameters;", -1, &pStmt, 0); - if( rx==SQLITE_OK && sqlite3_step(pStmt)==SQLITE_ROW ){ - len = sqlite3_column_int(pStmt, 0); - if( len>40 ) len = 40; - } - sqlite3_finalize(pStmt); - pStmt = 0; - if( len ){ - rx = sqlite3_prepare_v2(p->db, - "SELECT key, quote(value) " - "FROM temp.sqlite_parameters;", -1, &pStmt, 0); - while( rx==SQLITE_OK && sqlite3_step(pStmt)==SQLITE_ROW ){ - utf8_printf(p->out, "%-*s %s\n", len, sqlite3_column_text(pStmt,0), - sqlite3_column_text(pStmt,1)); - } - sqlite3_finalize(pStmt); - } - }else - - /* .parameter init + if( nArg==2 && strcmp(azArg[1],"list")==0 ){ + sqlite3_stmt *pStmt = 0; + int rx; + int len = 0; + rx = sqlite3_prepare_v2(p->db, + "SELECT max(length(key)) " + "FROM temp.sqlite_parameters;", -1, &pStmt, 0); + if( rx==SQLITE_OK && sqlite3_step(pStmt)==SQLITE_ROW ){ + len = sqlite3_column_int(pStmt, 0); + if( len>40 ) len = 40; + } + sqlite3_finalize(pStmt); + pStmt = 0; + if( len ){ + rx = sqlite3_prepare_v2(p->db, + "SELECT key, quote(value) " + "FROM temp.sqlite_parameters;", -1, &pStmt, 0); + while( rx==SQLITE_OK && sqlite3_step(pStmt)==SQLITE_ROW ){ + utf8_printf(p->out, "%-*s %s\n", len, sqlite3_column_text(pStmt,0), + sqlite3_column_text(pStmt,1)); + } + sqlite3_finalize(pStmt); + } + }else + + /* .parameter init ** Make sure the TEMP table used to hold bind parameters exists. ** Create it if necessary. */ - if( nArg==2 && strcmp(azArg[1],"init")==0 ){ - bind_table_init(p); - }else + if( nArg==2 && strcmp(azArg[1],"init")==0 ){ + bind_table_init(p); + }else - /* .parameter set NAME VALUE + /* .parameter set NAME VALUE ** Set or reset a bind parameter. NAME should be the full parameter ** name exactly as it appears in the query. (ex: $abc, @def). The ** VALUE can be in either SQL literal notation, or if not it will be ** understood to be a text string. */ - if( nArg==4 && strcmp(azArg[1],"set")==0 ){ - int rx; - char *zSql; - sqlite3_stmt *pStmt; - const char *zKey = azArg[2]; - const char *zValue = azArg[3]; - bind_table_init(p); - zSql = sqlite3_mprintf( - "REPLACE INTO temp.sqlite_parameters(key,value)" - "VALUES(%Q,%s);", zKey, zValue); - if( zSql==0 ) shell_out_of_memory(); - pStmt = 0; - rx = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); - sqlite3_free(zSql); - if( rx!=SQLITE_OK ){ - sqlite3_finalize(pStmt); - pStmt = 0; - zSql = sqlite3_mprintf( - "REPLACE INTO temp.sqlite_parameters(key,value)" - "VALUES(%Q,%Q);", zKey, zValue); - if( zSql==0 ) shell_out_of_memory(); - rx = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); - sqlite3_free(zSql); - if( rx!=SQLITE_OK ){ - utf8_printf(p->out, "Error: %s\n", sqlite3_errmsg(p->db)); - sqlite3_finalize(pStmt); - pStmt = 0; - rc = 1; - } - } - sqlite3_step(pStmt); - sqlite3_finalize(pStmt); - }else - - /* .parameter unset NAME + if( nArg==4 && strcmp(azArg[1],"set")==0 ){ + int rx; + char *zSql; + sqlite3_stmt *pStmt; + const char *zKey = azArg[2]; + const char *zValue = azArg[3]; + bind_table_init(p); + zSql = sqlite3_mprintf( + "REPLACE INTO temp.sqlite_parameters(key,value)" + "VALUES(%Q,%s);", zKey, zValue); + if( zSql==0 ) shell_out_of_memory(); + pStmt = 0; + rx = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); + sqlite3_free(zSql); + if( rx!=SQLITE_OK ){ + sqlite3_finalize(pStmt); + pStmt = 0; + zSql = sqlite3_mprintf( + "REPLACE INTO temp.sqlite_parameters(key,value)" + "VALUES(%Q,%Q);", zKey, zValue); + if( zSql==0 ) shell_out_of_memory(); + rx = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); + sqlite3_free(zSql); + if( rx!=SQLITE_OK ){ + utf8_printf(p->out, "Error: %s\n", sqlite3_errmsg(p->db)); + sqlite3_finalize(pStmt); + pStmt = 0; + rc = 1; + } + } + sqlite3_step(pStmt); + sqlite3_finalize(pStmt); + }else + + /* .parameter unset NAME ** Remove the NAME binding from the parameter binding table, if it ** exists. */ - if( nArg==3 && strcmp(azArg[1],"unset")==0 ){ - char *zSql = sqlite3_mprintf( - "DELETE FROM temp.sqlite_parameters WHERE key=%Q", azArg[2]); - if( zSql==0 ) shell_out_of_memory(); - sqlite3_exec(p->db, zSql, 0, 0, 0); - sqlite3_free(zSql); - }else - /* If no command name matches, show a syntax error */ - parameter_syntax_error: - showHelp(p->out, "parameter"); - }else - - if( c=='p' && n>=3 && strncmp(azArg[0], "print", n)==0 ){ - int i; - for(i=1; i1 ) raw_printf(p->out, " "); - utf8_printf(p->out, "%s", azArg[i]); - } - raw_printf(p->out, "\n"); - }else + if( nArg==3 && strcmp(azArg[1],"unset")==0 ){ + char *zSql = sqlite3_mprintf( + "DELETE FROM temp.sqlite_parameters WHERE key=%Q", azArg[2]); + if( zSql==0 ) shell_out_of_memory(); + sqlite3_exec(p->db, zSql, 0, 0, 0); + sqlite3_free(zSql); + }else + /* If no command name matches, show a syntax error */ + parameter_syntax_error: + showHelp(p->out, "parameter"); + }else + + if( c=='p' && n>=3 && strncmp(azArg[0], "print", n)==0 ){ + int i; + for(i=1; i1 ) raw_printf(p->out, " "); + utf8_printf(p->out, "%s", azArg[i]); + } + raw_printf(p->out, "\n"); + }else #ifndef SQLITE_OMIT_PROGRESS_CALLBACK - if( c=='p' && n>=3 && strncmp(azArg[0], "progress", n)==0 ){ - int i; - int nn = 0; - p->flgProgress = 0; - p->mxProgress = 0; - p->nProgress = 0; - for(i=1; iflgProgress |= SHELL_PROGRESS_QUIET; - continue; - } - if( strcmp(z,"reset")==0 ){ - p->flgProgress |= SHELL_PROGRESS_RESET; - continue; - } - if( strcmp(z,"once")==0 ){ - p->flgProgress |= SHELL_PROGRESS_ONCE; - continue; - } - if( strcmp(z,"limit")==0 ){ - if( i+1>=nArg ){ - utf8_printf(stderr, "Error: missing argument on --limit\n"); - rc = 1; - goto meta_command_exit; - }else{ - p->mxProgress = (int)integerValue(azArg[++i]); - } - continue; - } - utf8_printf(stderr, "Error: unknown option: \"%s\"\n", azArg[i]); - rc = 1; - goto meta_command_exit; - }else{ - nn = (int)integerValue(z); - } - } - open_db(p, 0); - sqlite3_progress_handler(p->db, nn, progress_handler, p); - }else + if( c=='p' && n>=3 && strncmp(azArg[0], "progress", n)==0 ){ + int i; + int nn = 0; + p->flgProgress = 0; + p->mxProgress = 0; + p->nProgress = 0; + for(i=1; iflgProgress |= SHELL_PROGRESS_QUIET; + continue; + } + if( strcmp(z,"reset")==0 ){ + p->flgProgress |= SHELL_PROGRESS_RESET; + continue; + } + if( strcmp(z,"once")==0 ){ + p->flgProgress |= SHELL_PROGRESS_ONCE; + continue; + } + if( strcmp(z,"limit")==0 ){ + if( i+1>=nArg ){ + utf8_printf(stderr, "Error: missing argument on --limit\n"); + rc = 1; + goto meta_command_exit; + }else{ + p->mxProgress = (int)integerValue(azArg[++i]); + } + continue; + } + utf8_printf(stderr, "Error: unknown option: \"%s\"\n", azArg[i]); + rc = 1; + goto meta_command_exit; + }else{ + nn = (int)integerValue(z); + } + } + open_db(p, 0); + sqlite3_progress_handler(p->db, nn, progress_handler, p); + }else #endif /* SQLITE_OMIT_PROGRESS_CALLBACK */ - if( c=='p' && strncmp(azArg[0], "prompt", n)==0 ){ - if( nArg >= 2) { - strncpy(mainPrompt,azArg[1],(int)ArraySize(mainPrompt)-1); - } - if( nArg >= 3) { - strncpy(continuePrompt,azArg[2],(int)ArraySize(continuePrompt)-1); - } - }else - - if( c=='q' && strncmp(azArg[0], "quit", n)==0 ){ - rc = 2; - }else - - if( c=='r' && n>=3 && strncmp(azArg[0], "read", n)==0 ){ - FILE *inSaved = p->in; - int savedLineno = p->lineno; - failIfSafeMode(p, "cannot run .read in safe mode"); - if( nArg!=2 ){ - raw_printf(stderr, "Usage: .read FILE\n"); - rc = 1; - goto meta_command_exit; - } - if( azArg[1][0]=='|' ){ + if( c=='p' && strncmp(azArg[0], "prompt", n)==0 ){ + if( nArg >= 2) { + strncpy(mainPrompt,azArg[1],(int)ArraySize(mainPrompt)-1); + } + if( nArg >= 3) { + strncpy(continuePrompt,azArg[2],(int)ArraySize(continuePrompt)-1); + } + }else + + if( c=='q' && strncmp(azArg[0], "quit", n)==0 ){ + rc = 2; + }else + + if( c=='r' && n>=3 && strncmp(azArg[0], "read", n)==0 ){ + FILE *inSaved = p->in; + int savedLineno = p->lineno; + failIfSafeMode(p, "cannot run .read in safe mode"); + if( nArg!=2 ){ + raw_printf(stderr, "Usage: .read FILE\n"); + rc = 1; + goto meta_command_exit; + } + if( azArg[1][0]=='|' ){ #ifdef SQLITE_OMIT_POPEN - raw_printf(stderr, "Error: pipes are not supported in this OS\n"); - rc = 1; - p->out = stdout; + raw_printf(stderr, "Error: pipes are not supported in this OS\n"); + rc = 1; + p->out = stdout; #else - p->in = popen(azArg[1]+1, "r"); - if( p->in==0 ){ - utf8_printf(stderr, "Error: cannot open \"%s\"\n", azArg[1]); - rc = 1; - }else{ - rc = process_input(p); - pclose(p->in); - } + p->in = popen(azArg[1]+1, "r"); + if( p->in==0 ){ + utf8_printf(stderr, "Error: cannot open \"%s\"\n", azArg[1]); + rc = 1; + }else{ + rc = process_input(p); + pclose(p->in); + } #endif - }else if( (p->in = openChrSource(azArg[1]))==0 ){ - utf8_printf(stderr,"Error: cannot open \"%s\"\n", azArg[1]); - rc = 1; - }else{ - rc = process_input(p); - fclose(p->in); - } - p->in = inSaved; - p->lineno = savedLineno; - }else - - if( c=='r' && n>=3 && strncmp(azArg[0], "restore", n)==0 ){ - const char *zSrcFile; - const char *zDb; - sqlite3 *pSrc; - sqlite3_backup *pBackup; - int nTimeout = 0; - - failIfSafeMode(p, "cannot run .restore in safe mode"); - if( nArg==2 ){ - zSrcFile = azArg[1]; - zDb = "main"; - }else if( nArg==3 ){ - zSrcFile = azArg[2]; - zDb = azArg[1]; - }else{ - raw_printf(stderr, "Usage: .restore ?DB? FILE\n"); - rc = 1; - goto meta_command_exit; - } - rc = sqlite3_open(zSrcFile, &pSrc); - if( rc!=SQLITE_OK ){ - utf8_printf(stderr, "Error: cannot open \"%s\"\n", zSrcFile); - close_db(pSrc); - return 1; - } - open_db(p, 0); - pBackup = sqlite3_backup_init(p->db, zDb, pSrc, "main"); - if( pBackup==0 ){ - utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db)); - close_db(pSrc); - return 1; - } - while( (rc = sqlite3_backup_step(pBackup,100))==SQLITE_OK - || rc==SQLITE_BUSY ){ - if( rc==SQLITE_BUSY ){ - if( nTimeout++ >= 3 ) break; - sqlite3_sleep(100); - } - } - sqlite3_backup_finish(pBackup); - if( rc==SQLITE_DONE ){ - rc = 0; - }else if( rc==SQLITE_BUSY || rc==SQLITE_LOCKED ){ - raw_printf(stderr, "Error: source database is busy\n"); - rc = 1; - }else{ - utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db)); - rc = 1; - } - close_db(pSrc); - }else - - if( c=='s' && strncmp(azArg[0], "scanstats", n)==0 ){ - if( nArg==2 ){ - p->scanstatsOn = (u8)booleanValue(azArg[1]); + }else if( (p->in = openChrSource(azArg[1]))==0 ){ + utf8_printf(stderr,"Error: cannot open \"%s\"\n", azArg[1]); + rc = 1; + }else{ + rc = process_input(p); + fclose(p->in); + } + p->in = inSaved; + p->lineno = savedLineno; + }else + + if( c=='r' && n>=3 && strncmp(azArg[0], "restore", n)==0 ){ + const char *zSrcFile; + const char *zDb; + sqlite3 *pSrc; + sqlite3_backup *pBackup; + int nTimeout = 0; + + failIfSafeMode(p, "cannot run .restore in safe mode"); + if( nArg==2 ){ + zSrcFile = azArg[1]; + zDb = "main"; + }else if( nArg==3 ){ + zSrcFile = azArg[2]; + zDb = azArg[1]; + }else{ + raw_printf(stderr, "Usage: .restore ?DB? FILE\n"); + rc = 1; + goto meta_command_exit; + } + rc = sqlite3_open(zSrcFile, &pSrc); + if( rc!=SQLITE_OK ){ + utf8_printf(stderr, "Error: cannot open \"%s\"\n", zSrcFile); + close_db(pSrc); + return 1; + } + open_db(p, 0); + pBackup = sqlite3_backup_init(p->db, zDb, pSrc, "main"); + if( pBackup==0 ){ + utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db)); + close_db(pSrc); + return 1; + } + while( (rc = sqlite3_backup_step(pBackup,100))==SQLITE_OK + || rc==SQLITE_BUSY ){ + if( rc==SQLITE_BUSY ){ + if( nTimeout++ >= 3 ) break; + sqlite3_sleep(100); + } + } + sqlite3_backup_finish(pBackup); + if( rc==SQLITE_DONE ){ + rc = 0; + }else if( rc==SQLITE_BUSY || rc==SQLITE_LOCKED ){ + raw_printf(stderr, "Error: source database is busy\n"); + rc = 1; + }else{ + utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db)); + rc = 1; + } + close_db(pSrc); + }else + + if( c=='s' && strncmp(azArg[0], "scanstats", n)==0 ){ + if( nArg==2 ){ + p->scanstatsOn = (u8)booleanValue(azArg[1]); #ifndef SQLITE_ENABLE_STMT_SCANSTATUS - raw_printf(stderr, "Warning: .scanstats not available in this build.\n"); + raw_printf(stderr, "Warning: .scanstats not available in this build.\n"); #endif - }else{ - raw_printf(stderr, "Usage: .scanstats on|off\n"); - rc = 1; - } - }else - - if( c=='s' && strncmp(azArg[0], "schema", n)==0 ){ - ShellText sSelect; - ShellState data; - char *zErrMsg = 0; - const char *zDiv = "("; - const char *zName = 0; - int iSchema = 0; - int bDebug = 0; - int bNoSystemTabs = 0; - int ii; - - open_db(p, 0); - memcpy(&data, p, sizeof(data)); - data.showHeader = 0; - data.cMode = data.mode = MODE_Semi; - initText(&sSelect); - for(ii=1; iidb, "SELECT name FROM pragma_database_list", - -1, &pStmt, 0); - if( rc ){ - utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db)); - sqlite3_finalize(pStmt); - rc = 1; - goto meta_command_exit; - } - appendText(&sSelect, "SELECT sql FROM", 0); - iSchema = 0; - while( sqlite3_step(pStmt)==SQLITE_ROW ){ - const char *zDb = (const char*)sqlite3_column_text(pStmt, 0); - char zScNum[30]; - sqlite3_snprintf(sizeof(zScNum), zScNum, "%d", ++iSchema); - appendText(&sSelect, zDiv, 0); - zDiv = " UNION ALL "; - appendText(&sSelect, "SELECT shell_add_schema(sql,", 0); - if( sqlite3_stricmp(zDb, "main")!=0 ){ - appendText(&sSelect, zDb, '\''); - }else{ - appendText(&sSelect, "NULL", 0); - } - appendText(&sSelect, ",name) AS sql, type, tbl_name, name, rowid,", 0); - appendText(&sSelect, zScNum, 0); - appendText(&sSelect, " AS snum, ", 0); - appendText(&sSelect, zDb, '\''); - appendText(&sSelect, " AS sname FROM ", 0); - appendText(&sSelect, zDb, quoteChar(zDb)); - appendText(&sSelect, ".sqlite_schema", 0); - } - sqlite3_finalize(pStmt); + }else{ + raw_printf(stderr, "Usage: .scanstats on|off\n"); + rc = 1; + } + }else + + if( c=='s' && strncmp(azArg[0], "schema", n)==0 ){ + ShellText sSelect; + ShellState data; + char *zErrMsg = 0; + const char *zDiv = "("; + const char *zName = 0; + int iSchema = 0; + int bDebug = 0; + int bNoSystemTabs = 0; + int ii; + + open_db(p, 0); + memcpy(&data, p, sizeof(data)); + data.showHeader = 0; + data.cMode = data.mode = MODE_Semi; + initText(&sSelect); + for(ii=1; iidb, "SELECT name FROM pragma_database_list", + -1, &pStmt, 0); + if( rc ){ + utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db)); + sqlite3_finalize(pStmt); + rc = 1; + goto meta_command_exit; + } + appendText(&sSelect, "SELECT sql FROM", 0); + iSchema = 0; + while( sqlite3_step(pStmt)==SQLITE_ROW ){ + const char *zDb = (const char*)sqlite3_column_text(pStmt, 0); + char zScNum[30]; + sqlite3_snprintf(sizeof(zScNum), zScNum, "%d", ++iSchema); + appendText(&sSelect, zDiv, 0); + zDiv = " UNION ALL "; + appendText(&sSelect, "SELECT shell_add_schema(sql,", 0); + if( sqlite3_stricmp(zDb, "main")!=0 ){ + appendText(&sSelect, zDb, '\''); + }else{ + appendText(&sSelect, "NULL", 0); + } + appendText(&sSelect, ",name) AS sql, type, tbl_name, name, rowid,", 0); + appendText(&sSelect, zScNum, 0); + appendText(&sSelect, " AS snum, ", 0); + appendText(&sSelect, zDb, '\''); + appendText(&sSelect, " AS sname FROM ", 0); + appendText(&sSelect, zDb, quoteChar(zDb)); + appendText(&sSelect, ".sqlite_schema", 0); + } + sqlite3_finalize(pStmt); #ifndef SQLITE_OMIT_INTROSPECTION_PRAGMAS - if( zName ){ - appendText(&sSelect, - " UNION ALL SELECT shell_module_schema(name)," - " 'table', name, name, name, 9e+99, 'main' FROM pragma_module_list", - 0); - } + if( zName ){ + appendText(&sSelect, + " UNION ALL SELECT shell_module_schema(name)," + " 'table', name, name, name, 9e+99, 'main' FROM pragma_module_list", + 0); + } #endif - appendText(&sSelect, ") WHERE ", 0); - if( zName ){ - char *zQarg = sqlite3_mprintf("%Q", zName); - int bGlob = strchr(zName, '*') != 0 || strchr(zName, '?') != 0 || - strchr(zName, '[') != 0; - if( strchr(zName, '.') ){ - appendText(&sSelect, "lower(printf('%s.%s',sname,tbl_name))", 0); - }else{ - appendText(&sSelect, "lower(tbl_name)", 0); - } - appendText(&sSelect, bGlob ? " GLOB " : " LIKE ", 0); - appendText(&sSelect, zQarg, 0); - if( !bGlob ){ - appendText(&sSelect, " ESCAPE '\\' ", 0); - } - appendText(&sSelect, " AND ", 0); - sqlite3_free(zQarg); - } - if( bNoSystemTabs ){ - appendText(&sSelect, "name NOT LIKE 'sqlite_%%' AND ", 0); - } - appendText(&sSelect, "sql IS NOT NULL" - " ORDER BY snum, rowid", 0); - if( bDebug ){ - utf8_printf(p->out, "SQL: %s;\n", sSelect.z); - }else{ - rc = sqlite3_exec(p->db, sSelect.z, callback, &data, &zErrMsg); - } - freeText(&sSelect); - } - if( zErrMsg ){ - utf8_printf(stderr,"Error: %s\n", zErrMsg); - sqlite3_free(zErrMsg); - rc = 1; - }else if( rc != SQLITE_OK ){ - raw_printf(stderr,"Error: querying schema information\n"); - rc = 1; - }else{ - rc = 0; - } - }else - - if( c=='s' && n==11 && strncmp(azArg[0], "selecttrace", n)==0 ){ - unsigned int x = nArg>=2 ? (unsigned int)integerValue(azArg[1]) : 0xffffffff; - sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 1, &x); - }else + appendText(&sSelect, ") WHERE ", 0); + if( zName ){ + char *zQarg = sqlite3_mprintf("%Q", zName); + int bGlob = strchr(zName, '*') != 0 || strchr(zName, '?') != 0 || + strchr(zName, '[') != 0; + if( strchr(zName, '.') ){ + appendText(&sSelect, "lower(printf('%s.%s',sname,tbl_name))", 0); + }else{ + appendText(&sSelect, "lower(tbl_name)", 0); + } + appendText(&sSelect, bGlob ? " GLOB " : " LIKE ", 0); + appendText(&sSelect, zQarg, 0); + if( !bGlob ){ + appendText(&sSelect, " ESCAPE '\\' ", 0); + } + appendText(&sSelect, " AND ", 0); + sqlite3_free(zQarg); + } + if( bNoSystemTabs ){ + appendText(&sSelect, "name NOT LIKE 'sqlite_%%' AND ", 0); + } + appendText(&sSelect, "sql IS NOT NULL" + " ORDER BY snum, rowid", 0); + if( bDebug ){ + utf8_printf(p->out, "SQL: %s;\n", sSelect.z); + }else{ + rc = sqlite3_exec(p->db, sSelect.z, callback, &data, &zErrMsg); + } + freeText(&sSelect); + } + if( zErrMsg ){ + utf8_printf(stderr,"Error: %s\n", zErrMsg); + sqlite3_free(zErrMsg); + rc = 1; + }else if( rc != SQLITE_OK ){ + raw_printf(stderr,"Error: querying schema information\n"); + rc = 1; + }else{ + rc = 0; + } + }else + + if( c=='s' && n==11 && strncmp(azArg[0], "selecttrace", n)==0 ){ + unsigned int x = nArg>=2 ? (unsigned int)integerValue(azArg[1]) : 0xffffffff; + sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 1, &x); + }else #if defined(SQLITE_ENABLE_SESSION) - if( c=='s' && strncmp(azArg[0],"session",n)==0 && n>=3 ){ - struct AuxDb *pAuxDb = p->pAuxDb; - OpenSession *pSession = &pAuxDb->aSession[0]; - char **azCmd = &azArg[1]; - int iSes = 0; - int nCmd = nArg - 1; - int i; - if( nArg<=1 ) goto session_syntax_error; - open_db(p, 0); - if( nArg>=3 ){ - for(iSes=0; iSesnSession; iSes++){ - if( strcmp(pAuxDb->aSession[iSes].zName, azArg[1])==0 ) break; - } - if( iSesnSession ){ - pSession = &pAuxDb->aSession[iSes]; - azCmd++; - nCmd--; - }else{ - pSession = &pAuxDb->aSession[0]; - iSes = 0; - } - } - - /* .session attach TABLE + if( c=='s' && strncmp(azArg[0],"session",n)==0 && n>=3 ){ + struct AuxDb *pAuxDb = p->pAuxDb; + OpenSession *pSession = &pAuxDb->aSession[0]; + char **azCmd = &azArg[1]; + int iSes = 0; + int nCmd = nArg - 1; + int i; + if( nArg<=1 ) goto session_syntax_error; + open_db(p, 0); + if( nArg>=3 ){ + for(iSes=0; iSesnSession; iSes++){ + if( strcmp(pAuxDb->aSession[iSes].zName, azArg[1])==0 ) break; + } + if( iSesnSession ){ + pSession = &pAuxDb->aSession[iSes]; + azCmd++; + nCmd--; + }else{ + pSession = &pAuxDb->aSession[0]; + iSes = 0; + } + } + + /* .session attach TABLE ** Invoke the sqlite3session_attach() interface to attach a particular ** table so that it is never filtered. */ - if( strcmp(azCmd[0],"attach")==0 ){ - if( nCmd!=2 ) goto session_syntax_error; - if( pSession->p==0 ){ - session_not_open: - raw_printf(stderr, "ERROR: No sessions are open\n"); - }else{ - rc = sqlite3session_attach(pSession->p, azCmd[1]); - if( rc ){ - raw_printf(stderr, "ERROR: sqlite3session_attach() returns %d\n", rc); - rc = 0; - } - } - }else - - /* .session changeset FILE + if( strcmp(azCmd[0],"attach")==0 ){ + if( nCmd!=2 ) goto session_syntax_error; + if( pSession->p==0 ){ + session_not_open: + raw_printf(stderr, "ERROR: No sessions are open\n"); + }else{ + rc = sqlite3session_attach(pSession->p, azCmd[1]); + if( rc ){ + raw_printf(stderr, "ERROR: sqlite3session_attach() returns %d\n", rc); + rc = 0; + } + } + }else + + /* .session changeset FILE ** .session patchset FILE ** Write a changeset or patchset into a file. The file is overwritten. */ - if( strcmp(azCmd[0],"changeset")==0 || strcmp(azCmd[0],"patchset")==0 ){ - FILE *out = 0; - failIfSafeMode(p, "cannot run \".session %s\" in safe mode", azCmd[0]); - if( nCmd!=2 ) goto session_syntax_error; - if( pSession->p==0 ) goto session_not_open; - out = fopen(azCmd[1], "wb"); - if( out==0 ){ - utf8_printf(stderr, "ERROR: cannot open \"%s\" for writing\n", - azCmd[1]); - }else{ - int szChng; - void *pChng; - if( azCmd[0][0]=='c' ){ - rc = sqlite3session_changeset(pSession->p, &szChng, &pChng); - }else{ - rc = sqlite3session_patchset(pSession->p, &szChng, &pChng); - } - if( rc ){ - printf("Error: error code %d\n", rc); - rc = 0; - } - if( pChng - && fwrite(pChng, szChng, 1, out)!=1 ){ - raw_printf(stderr, "ERROR: Failed to write entire %d-byte output\n", - szChng); - } - sqlite3_free(pChng); - fclose(out); - } - }else - - /* .session close + if( strcmp(azCmd[0],"changeset")==0 || strcmp(azCmd[0],"patchset")==0 ){ + FILE *out = 0; + failIfSafeMode(p, "cannot run \".session %s\" in safe mode", azCmd[0]); + if( nCmd!=2 ) goto session_syntax_error; + if( pSession->p==0 ) goto session_not_open; + out = fopen(azCmd[1], "wb"); + if( out==0 ){ + utf8_printf(stderr, "ERROR: cannot open \"%s\" for writing\n", + azCmd[1]); + }else{ + int szChng; + void *pChng; + if( azCmd[0][0]=='c' ){ + rc = sqlite3session_changeset(pSession->p, &szChng, &pChng); + }else{ + rc = sqlite3session_patchset(pSession->p, &szChng, &pChng); + } + if( rc ){ + printf("Error: error code %d\n", rc); + rc = 0; + } + if( pChng + && fwrite(pChng, szChng, 1, out)!=1 ){ + raw_printf(stderr, "ERROR: Failed to write entire %d-byte output\n", + szChng); + } + sqlite3_free(pChng); + fclose(out); + } + }else + + /* .session close ** Close the identified session */ - if( strcmp(azCmd[0], "close")==0 ){ - if( nCmd!=1 ) goto session_syntax_error; - if( pAuxDb->nSession ){ - session_close(pSession); - pAuxDb->aSession[iSes] = pAuxDb->aSession[--pAuxDb->nSession]; - } - }else - - /* .session enable ?BOOLEAN? + if( strcmp(azCmd[0], "close")==0 ){ + if( nCmd!=1 ) goto session_syntax_error; + if( pAuxDb->nSession ){ + session_close(pSession); + pAuxDb->aSession[iSes] = pAuxDb->aSession[--pAuxDb->nSession]; + } + }else + + /* .session enable ?BOOLEAN? ** Query or set the enable flag */ - if( strcmp(azCmd[0], "enable")==0 ){ - int ii; - if( nCmd>2 ) goto session_syntax_error; - ii = nCmd==1 ? -1 : booleanValue(azCmd[1]); - if( pAuxDb->nSession ){ - ii = sqlite3session_enable(pSession->p, ii); - utf8_printf(p->out, "session %s enable flag = %d\n", - pSession->zName, ii); - } - }else - - /* .session filter GLOB .... + if( strcmp(azCmd[0], "enable")==0 ){ + int ii; + if( nCmd>2 ) goto session_syntax_error; + ii = nCmd==1 ? -1 : booleanValue(azCmd[1]); + if( pAuxDb->nSession ){ + ii = sqlite3session_enable(pSession->p, ii); + utf8_printf(p->out, "session %s enable flag = %d\n", + pSession->zName, ii); + } + }else + + /* .session filter GLOB .... ** Set a list of GLOB patterns of table names to be excluded. */ - if( strcmp(azCmd[0], "filter")==0 ){ - int ii, nByte; - if( nCmd<2 ) goto session_syntax_error; - if( pAuxDb->nSession ){ - for(ii=0; iinFilter; ii++){ - sqlite3_free(pSession->azFilter[ii]); - } - sqlite3_free(pSession->azFilter); - nByte = sizeof(pSession->azFilter[0])*(nCmd-1); - pSession->azFilter = sqlite3_malloc( nByte ); - if( pSession->azFilter==0 ){ - raw_printf(stderr, "Error: out or memory\n"); - exit(1); - } - for(ii=1; iiazFilter[ii-1] = sqlite3_mprintf("%s", azCmd[ii]); - } - pSession->nFilter = ii-1; - } - }else - - /* .session indirect ?BOOLEAN? + if( strcmp(azCmd[0], "filter")==0 ){ + int ii, nByte; + if( nCmd<2 ) goto session_syntax_error; + if( pAuxDb->nSession ){ + for(ii=0; iinFilter; ii++){ + sqlite3_free(pSession->azFilter[ii]); + } + sqlite3_free(pSession->azFilter); + nByte = sizeof(pSession->azFilter[0])*(nCmd-1); + pSession->azFilter = sqlite3_malloc( nByte ); + if( pSession->azFilter==0 ){ + raw_printf(stderr, "Error: out or memory\n"); + exit(1); + } + for(ii=1; iiazFilter[ii-1] = sqlite3_mprintf("%s", azCmd[ii]); + } + pSession->nFilter = ii-1; + } + }else + + /* .session indirect ?BOOLEAN? ** Query or set the indirect flag */ - if( strcmp(azCmd[0], "indirect")==0 ){ - int ii; - if( nCmd>2 ) goto session_syntax_error; - ii = nCmd==1 ? -1 : booleanValue(azCmd[1]); - if( pAuxDb->nSession ){ - ii = sqlite3session_indirect(pSession->p, ii); - utf8_printf(p->out, "session %s indirect flag = %d\n", - pSession->zName, ii); - } - }else - - /* .session isempty + if( strcmp(azCmd[0], "indirect")==0 ){ + int ii; + if( nCmd>2 ) goto session_syntax_error; + ii = nCmd==1 ? -1 : booleanValue(azCmd[1]); + if( pAuxDb->nSession ){ + ii = sqlite3session_indirect(pSession->p, ii); + utf8_printf(p->out, "session %s indirect flag = %d\n", + pSession->zName, ii); + } + }else + + /* .session isempty ** Determine if the session is empty */ - if( strcmp(azCmd[0], "isempty")==0 ){ - int ii; - if( nCmd!=1 ) goto session_syntax_error; - if( pAuxDb->nSession ){ - ii = sqlite3session_isempty(pSession->p); - utf8_printf(p->out, "session %s isempty flag = %d\n", - pSession->zName, ii); - } - }else - - /* .session list + if( strcmp(azCmd[0], "isempty")==0 ){ + int ii; + if( nCmd!=1 ) goto session_syntax_error; + if( pAuxDb->nSession ){ + ii = sqlite3session_isempty(pSession->p); + utf8_printf(p->out, "session %s isempty flag = %d\n", + pSession->zName, ii); + } + }else + + /* .session list ** List all currently open sessions */ - if( strcmp(azCmd[0],"list")==0 ){ - for(i=0; inSession; i++){ - utf8_printf(p->out, "%d %s\n", i, pAuxDb->aSession[i].zName); - } - }else + if( strcmp(azCmd[0],"list")==0 ){ + for(i=0; inSession; i++){ + utf8_printf(p->out, "%d %s\n", i, pAuxDb->aSession[i].zName); + } + }else - /* .session open DB NAME + /* .session open DB NAME ** Open a new session called NAME on the attached database DB. ** DB is normally "main". */ - if( strcmp(azCmd[0],"open")==0 ){ - char *zName; - if( nCmd!=3 ) goto session_syntax_error; - zName = azCmd[2]; - if( zName[0]==0 ) goto session_syntax_error; - for(i=0; inSession; i++){ - if( strcmp(pAuxDb->aSession[i].zName,zName)==0 ){ - utf8_printf(stderr, "Session \"%s\" already exists\n", zName); - goto meta_command_exit; - } - } - if( pAuxDb->nSession>=ArraySize(pAuxDb->aSession) ){ - raw_printf(stderr, "Maximum of %d sessions\n", ArraySize(pAuxDb->aSession)); - goto meta_command_exit; - } - pSession = &pAuxDb->aSession[pAuxDb->nSession]; - rc = sqlite3session_create(p->db, azCmd[1], &pSession->p); - if( rc ){ - raw_printf(stderr, "Cannot open session: error code=%d\n", rc); - rc = 0; - goto meta_command_exit; - } - pSession->nFilter = 0; - sqlite3session_table_filter(pSession->p, session_filter, pSession); - pAuxDb->nSession++; - pSession->zName = sqlite3_mprintf("%s", zName); - }else - /* If no command name matches, show a syntax error */ - session_syntax_error: - showHelp(p->out, "session"); - }else + if( strcmp(azCmd[0],"open")==0 ){ + char *zName; + if( nCmd!=3 ) goto session_syntax_error; + zName = azCmd[2]; + if( zName[0]==0 ) goto session_syntax_error; + for(i=0; inSession; i++){ + if( strcmp(pAuxDb->aSession[i].zName,zName)==0 ){ + utf8_printf(stderr, "Session \"%s\" already exists\n", zName); + goto meta_command_exit; + } + } + if( pAuxDb->nSession>=ArraySize(pAuxDb->aSession) ){ + raw_printf(stderr, "Maximum of %d sessions\n", ArraySize(pAuxDb->aSession)); + goto meta_command_exit; + } + pSession = &pAuxDb->aSession[pAuxDb->nSession]; + rc = sqlite3session_create(p->db, azCmd[1], &pSession->p); + if( rc ){ + raw_printf(stderr, "Cannot open session: error code=%d\n", rc); + rc = 0; + goto meta_command_exit; + } + pSession->nFilter = 0; + sqlite3session_table_filter(pSession->p, session_filter, pSession); + pAuxDb->nSession++; + pSession->zName = sqlite3_mprintf("%s", zName); + }else + /* If no command name matches, show a syntax error */ + session_syntax_error: + showHelp(p->out, "session"); + }else #endif #ifdef SQLITE_DEBUG - /* Undocumented commands for internal testing. Subject to change + /* Undocumented commands for internal testing. Subject to change ** without notice. */ - if( c=='s' && n>=10 && strncmp(azArg[0], "selftest-", 9)==0 ){ - if( strncmp(azArg[0]+9, "boolean", n-9)==0 ){ - int i, v; - for(i=1; iout, "%s: %d 0x%x\n", azArg[i], v, v); - } - } - if( strncmp(azArg[0]+9, "integer", n-9)==0 ){ - int i; sqlite3_int64 v; - for(i=1; iout, "%s", zBuf); - } - } - }else + if( c=='s' && n>=10 && strncmp(azArg[0], "selftest-", 9)==0 ){ + if( strncmp(azArg[0]+9, "boolean", n-9)==0 ){ + int i, v; + for(i=1; iout, "%s: %d 0x%x\n", azArg[i], v, v); + } + } + if( strncmp(azArg[0]+9, "integer", n-9)==0 ){ + int i; sqlite3_int64 v; + for(i=1; iout, "%s", zBuf); + } + } + }else #endif - if( c=='s' && n>=4 && strncmp(azArg[0],"selftest",n)==0 ){ - int bIsInit = 0; /* True to initialize the SELFTEST table */ - int bVerbose = 0; /* Verbose output */ - int bSelftestExists; /* True if SELFTEST already exists */ - int i, k; /* Loop counters */ - int nTest = 0; /* Number of tests runs */ - int nErr = 0; /* Number of errors seen */ - ShellText str; /* Answer for a query */ - sqlite3_stmt *pStmt = 0; /* Query against the SELFTEST table */ - - open_db(p,0); - for(i=1; idb,"main","selftest",0,0,0,0,0,0) - != SQLITE_OK ){ - bSelftestExists = 0; - }else{ - bSelftestExists = 1; - } - if( bIsInit ){ - createSelftestTable(p); - bSelftestExists = 1; - } - initText(&str); - appendText(&str, "x", 0); - for(k=bSelftestExists; k>=0; k--){ - if( k==1 ){ - rc = sqlite3_prepare_v2(p->db, - "SELECT tno,op,cmd,ans FROM selftest ORDER BY tno", - -1, &pStmt, 0); - }else{ - rc = sqlite3_prepare_v2(p->db, - "VALUES(0,'memo','Missing SELFTEST table - default checks only','')," - " (1,'run','PRAGMA integrity_check','ok')", - -1, &pStmt, 0); - } - if( rc ){ - raw_printf(stderr, "Error querying the selftest table\n"); - rc = 1; - sqlite3_finalize(pStmt); - goto meta_command_exit; - } - for(i=1; sqlite3_step(pStmt)==SQLITE_ROW; i++){ - int tno = sqlite3_column_int(pStmt, 0); - const char *zOp = (const char*)sqlite3_column_text(pStmt, 1); - const char *zSql = (const char*)sqlite3_column_text(pStmt, 2); - const char *zAns = (const char*)sqlite3_column_text(pStmt, 3); - - k = 0; - if( bVerbose>0 ){ - char *zQuote = sqlite3_mprintf("%q", zSql); - printf("%d: %s %s\n", tno, zOp, zSql); - sqlite3_free(zQuote); - } - if( strcmp(zOp,"memo")==0 ){ - utf8_printf(p->out, "%s\n", zSql); - }else - if( strcmp(zOp,"run")==0 ){ - char *zErrMsg = 0; - str.n = 0; - str.z[0] = 0; - rc = sqlite3_exec(p->db, zSql, captureOutputCallback, &str, &zErrMsg); - nTest++; - if( bVerbose ){ - utf8_printf(p->out, "Result: %s\n", str.z); - } - if( rc || zErrMsg ){ - nErr++; - rc = 1; - utf8_printf(p->out, "%d: error-code-%d: %s\n", tno, rc, zErrMsg); - sqlite3_free(zErrMsg); - }else if( strcmp(zAns,str.z)!=0 ){ - nErr++; - rc = 1; - utf8_printf(p->out, "%d: Expected: [%s]\n", tno, zAns); - utf8_printf(p->out, "%d: Got: [%s]\n", tno, str.z); - } - }else - { - utf8_printf(stderr, - "Unknown operation \"%s\" on selftest line %d\n", zOp, tno); - rc = 1; - break; - } - } /* End loop over rows of content from SELFTEST */ - sqlite3_finalize(pStmt); - } /* End loop over k */ - freeText(&str); - utf8_printf(p->out, "%d errors out of %d tests\n", nErr, nTest); - }else - - if( c=='s' && strncmp(azArg[0], "separator", n)==0 ){ - if( nArg<2 || nArg>3 ){ - raw_printf(stderr, "Usage: .separator COL ?ROW?\n"); - rc = 1; - } - if( nArg>=2 ){ - sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, - "%.*s", (int)ArraySize(p->colSeparator)-1, azArg[1]); - } - if( nArg>=3 ){ - sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, - "%.*s", (int)ArraySize(p->rowSeparator)-1, azArg[2]); - } - }else - - if( c=='s' && n>=4 && strncmp(azArg[0],"sha3sum",n)==0 ){ - const char *zLike = 0; /* Which table to checksum. 0 means everything */ - int i; /* Loop counter */ - int bSchema = 0; /* Also hash the schema */ - int bSeparate = 0; /* Hash each table separately */ - int iSize = 224; /* Hash algorithm to use */ - int bDebug = 0; /* Only show the query that would have run */ - sqlite3_stmt *pStmt; /* For querying tables names */ - char *zSql; /* SQL to be run */ - char *zSep; /* Separator */ - ShellText sSql; /* Complete SQL for the query to run the hash */ - ShellText sQuery; /* Set of queries used to read all content */ - open_db(p, 0); - for(i=1; iout, azArg[0]); - rc = 1; - goto meta_command_exit; - } - }else if( zLike ){ - raw_printf(stderr, "Usage: .sha3sum ?OPTIONS? ?LIKE-PATTERN?\n"); - rc = 1; - goto meta_command_exit; - }else{ - zLike = z; - bSeparate = 1; - if( sqlite3_strlike("sqlite\\_%", zLike, '\\')==0 ) bSchema = 1; - } - } - if( bSchema ){ - zSql = "SELECT lower(name) FROM sqlite_schema" - " WHERE type='table' AND coalesce(rootpage,0)>1" - " UNION ALL SELECT 'sqlite_schema'" - " ORDER BY 1 collate nocase"; - }else{ - zSql = "SELECT lower(name) FROM sqlite_schema" - " WHERE type='table' AND coalesce(rootpage,0)>1" - " AND name NOT LIKE 'sqlite_%'" - " ORDER BY 1 collate nocase"; - } - sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); - initText(&sQuery); - initText(&sSql); - appendText(&sSql, "WITH [sha3sum$query](a,b) AS(",0); - zSep = "VALUES("; - while( SQLITE_ROW==sqlite3_step(pStmt) ){ - const char *zTab = (const char*)sqlite3_column_text(pStmt,0); - if( zLike && sqlite3_strlike(zLike, zTab, 0)!=0 ) continue; - if( strncmp(zTab, "sqlite_",7)!=0 ){ - appendText(&sQuery,"SELECT * FROM ", 0); - appendText(&sQuery,zTab,'"'); - appendText(&sQuery," NOT INDEXED;", 0); - }else if( strcmp(zTab, "sqlite_schema")==0 ){ - appendText(&sQuery,"SELECT type,name,tbl_name,sql FROM sqlite_schema" - " ORDER BY name;", 0); - }else if( strcmp(zTab, "sqlite_sequence")==0 ){ - appendText(&sQuery,"SELECT name,seq FROM sqlite_sequence" - " ORDER BY name;", 0); - }else if( strcmp(zTab, "sqlite_stat1")==0 ){ - appendText(&sQuery,"SELECT tbl,idx,stat FROM sqlite_stat1" - " ORDER BY tbl,idx;", 0); - }else if( strcmp(zTab, "sqlite_stat4")==0 ){ - appendText(&sQuery, "SELECT * FROM ", 0); - appendText(&sQuery, zTab, 0); - appendText(&sQuery, " ORDER BY tbl, idx, rowid;\n", 0); - } - appendText(&sSql, zSep, 0); - appendText(&sSql, sQuery.z, '\''); - sQuery.n = 0; - appendText(&sSql, ",", 0); - appendText(&sSql, zTab, '\''); - zSep = "),("; - } - sqlite3_finalize(pStmt); - if( bSeparate ){ - zSql = sqlite3_mprintf( - "%s))" - " SELECT lower(hex(sha3_query(a,%d))) AS hash, b AS label" - " FROM [sha3sum$query]", - sSql.z, iSize); - }else{ - zSql = sqlite3_mprintf( - "%s))" - " SELECT lower(hex(sha3_query(group_concat(a,''),%d))) AS hash" - " FROM [sha3sum$query]", - sSql.z, iSize); - } - freeText(&sQuery); - freeText(&sSql); - if( bDebug ){ - utf8_printf(p->out, "%s\n", zSql); - }else{ - shell_exec(p, zSql, 0); - } - sqlite3_free(zSql); - }else + if( c=='s' && n>=4 && strncmp(azArg[0],"selftest",n)==0 ){ + int bIsInit = 0; /* True to initialize the SELFTEST table */ + int bVerbose = 0; /* Verbose output */ + int bSelftestExists; /* True if SELFTEST already exists */ + int i, k; /* Loop counters */ + int nTest = 0; /* Number of tests runs */ + int nErr = 0; /* Number of errors seen */ + ShellText str; /* Answer for a query */ + sqlite3_stmt *pStmt = 0; /* Query against the SELFTEST table */ + + open_db(p,0); + for(i=1; idb,"main","selftest",0,0,0,0,0,0) + != SQLITE_OK ){ + bSelftestExists = 0; + }else{ + bSelftestExists = 1; + } + if( bIsInit ){ + createSelftestTable(p); + bSelftestExists = 1; + } + initText(&str); + appendText(&str, "x", 0); + for(k=bSelftestExists; k>=0; k--){ + if( k==1 ){ + rc = sqlite3_prepare_v2(p->db, + "SELECT tno,op,cmd,ans FROM selftest ORDER BY tno", + -1, &pStmt, 0); + }else{ + rc = sqlite3_prepare_v2(p->db, + "VALUES(0,'memo','Missing SELFTEST table - default checks only','')," + " (1,'run','PRAGMA integrity_check','ok')", + -1, &pStmt, 0); + } + if( rc ){ + raw_printf(stderr, "Error querying the selftest table\n"); + rc = 1; + sqlite3_finalize(pStmt); + goto meta_command_exit; + } + for(i=1; sqlite3_step(pStmt)==SQLITE_ROW; i++){ + int tno = sqlite3_column_int(pStmt, 0); + const char *zOp = (const char*)sqlite3_column_text(pStmt, 1); + const char *zSql = (const char*)sqlite3_column_text(pStmt, 2); + const char *zAns = (const char*)sqlite3_column_text(pStmt, 3); + + k = 0; + if( bVerbose>0 ){ + char *zQuote = sqlite3_mprintf("%q", zSql); + printf("%d: %s %s\n", tno, zOp, zSql); + sqlite3_free(zQuote); + } + if( strcmp(zOp,"memo")==0 ){ + utf8_printf(p->out, "%s\n", zSql); + }else + if( strcmp(zOp,"run")==0 ){ + char *zErrMsg = 0; + str.n = 0; + str.z[0] = 0; + rc = sqlite3_exec(p->db, zSql, captureOutputCallback, &str, &zErrMsg); + nTest++; + if( bVerbose ){ + utf8_printf(p->out, "Result: %s\n", str.z); + } + if( rc || zErrMsg ){ + nErr++; + rc = 1; + utf8_printf(p->out, "%d: error-code-%d: %s\n", tno, rc, zErrMsg); + sqlite3_free(zErrMsg); + }else if( strcmp(zAns,str.z)!=0 ){ + nErr++; + rc = 1; + utf8_printf(p->out, "%d: Expected: [%s]\n", tno, zAns); + utf8_printf(p->out, "%d: Got: [%s]\n", tno, str.z); + } + }else + { + utf8_printf(stderr, + "Unknown operation \"%s\" on selftest line %d\n", zOp, tno); + rc = 1; + break; + } + } /* End loop over rows of content from SELFTEST */ + sqlite3_finalize(pStmt); + } /* End loop over k */ + freeText(&str); + utf8_printf(p->out, "%d errors out of %d tests\n", nErr, nTest); + }else + + if( c=='s' && strncmp(azArg[0], "separator", n)==0 ){ + if( nArg<2 || nArg>3 ){ + raw_printf(stderr, "Usage: .separator COL ?ROW?\n"); + rc = 1; + } + if( nArg>=2 ){ + sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, + "%.*s", (int)ArraySize(p->colSeparator)-1, azArg[1]); + } + if( nArg>=3 ){ + sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, + "%.*s", (int)ArraySize(p->rowSeparator)-1, azArg[2]); + } + }else + + if( c=='s' && n>=4 && strncmp(azArg[0],"sha3sum",n)==0 ){ + const char *zLike = 0; /* Which table to checksum. 0 means everything */ + int i; /* Loop counter */ + int bSchema = 0; /* Also hash the schema */ + int bSeparate = 0; /* Hash each table separately */ + int iSize = 224; /* Hash algorithm to use */ + int bDebug = 0; /* Only show the query that would have run */ + sqlite3_stmt *pStmt; /* For querying tables names */ + char *zSql; /* SQL to be run */ + char *zSep; /* Separator */ + ShellText sSql; /* Complete SQL for the query to run the hash */ + ShellText sQuery; /* Set of queries used to read all content */ + open_db(p, 0); + for(i=1; iout, azArg[0]); + rc = 1; + goto meta_command_exit; + } + }else if( zLike ){ + raw_printf(stderr, "Usage: .sha3sum ?OPTIONS? ?LIKE-PATTERN?\n"); + rc = 1; + goto meta_command_exit; + }else{ + zLike = z; + bSeparate = 1; + if( sqlite3_strlike("sqlite\\_%", zLike, '\\')==0 ) bSchema = 1; + } + } + if( bSchema ){ + zSql = "SELECT lower(name) FROM sqlite_schema" + " WHERE type='table' AND coalesce(rootpage,0)>1" + " UNION ALL SELECT 'sqlite_schema'" + " ORDER BY 1 collate nocase"; + }else{ + zSql = "SELECT lower(name) FROM sqlite_schema" + " WHERE type='table' AND coalesce(rootpage,0)>1" + " AND name NOT LIKE 'sqlite_%'" + " ORDER BY 1 collate nocase"; + } + sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); + initText(&sQuery); + initText(&sSql); + appendText(&sSql, "WITH [sha3sum$query](a,b) AS(",0); + zSep = "VALUES("; + while( SQLITE_ROW==sqlite3_step(pStmt) ){ + const char *zTab = (const char*)sqlite3_column_text(pStmt,0); + if( zLike && sqlite3_strlike(zLike, zTab, 0)!=0 ) continue; + if( strncmp(zTab, "sqlite_",7)!=0 ){ + appendText(&sQuery,"SELECT * FROM ", 0); + appendText(&sQuery,zTab,'"'); + appendText(&sQuery," NOT INDEXED;", 0); + }else if( strcmp(zTab, "sqlite_schema")==0 ){ + appendText(&sQuery,"SELECT type,name,tbl_name,sql FROM sqlite_schema" + " ORDER BY name;", 0); + }else if( strcmp(zTab, "sqlite_sequence")==0 ){ + appendText(&sQuery,"SELECT name,seq FROM sqlite_sequence" + " ORDER BY name;", 0); + }else if( strcmp(zTab, "sqlite_stat1")==0 ){ + appendText(&sQuery,"SELECT tbl,idx,stat FROM sqlite_stat1" + " ORDER BY tbl,idx;", 0); + }else if( strcmp(zTab, "sqlite_stat4")==0 ){ + appendText(&sQuery, "SELECT * FROM ", 0); + appendText(&sQuery, zTab, 0); + appendText(&sQuery, " ORDER BY tbl, idx, rowid;\n", 0); + } + appendText(&sSql, zSep, 0); + appendText(&sSql, sQuery.z, '\''); + sQuery.n = 0; + appendText(&sSql, ",", 0); + appendText(&sSql, zTab, '\''); + zSep = "),("; + } + sqlite3_finalize(pStmt); + if( bSeparate ){ + zSql = sqlite3_mprintf( + "%s))" + " SELECT lower(hex(sha3_query(a,%d))) AS hash, b AS label" + " FROM [sha3sum$query]", + sSql.z, iSize); + }else{ + zSql = sqlite3_mprintf( + "%s))" + " SELECT lower(hex(sha3_query(group_concat(a,''),%d))) AS hash" + " FROM [sha3sum$query]", + sSql.z, iSize); + } + freeText(&sQuery); + freeText(&sSql); + if( bDebug ){ + utf8_printf(p->out, "%s\n", zSql); + }else{ + shell_exec(p, zSql, 0); + } + sqlite3_free(zSql); + }else #ifndef SQLITE_NOHAVE_SYSTEM - if( c=='s' - && (strncmp(azArg[0], "shell", n)==0 || strncmp(azArg[0],"system",n)==0) - ){ - char *zCmd; - int i, x; - failIfSafeMode(p, "cannot run .%s in safe mode", azArg[0]); - if( nArg<2 ){ - raw_printf(stderr, "Usage: .system COMMAND\n"); - rc = 1; - goto meta_command_exit; - } - zCmd = sqlite3_mprintf(strchr(azArg[1],' ')==0?"%s":"\"%s\"", azArg[1]); - for(i=2; iout, "%12.12s: %s\n","echo", - azBool[ShellHasFlag(p, SHFLG_Echo)]); - utf8_printf(p->out, "%12.12s: %s\n","eqp", azBool[p->autoEQP&3]); - utf8_printf(p->out, "%12.12s: %s\n","explain", - p->mode==MODE_Explain ? "on" : p->autoExplain ? "auto" : "off"); - utf8_printf(p->out,"%12.12s: %s\n","headers", azBool[p->showHeader!=0]); - utf8_printf(p->out, "%12.12s: %s\n","mode", modeDescr[p->mode]); - utf8_printf(p->out, "%12.12s: ", "nullvalue"); - output_c_string(p->out, p->nullValue); - raw_printf(p->out, "\n"); - utf8_printf(p->out,"%12.12s: %s\n","output", - strlen30(p->outfile) ? p->outfile : "stdout"); - utf8_printf(p->out,"%12.12s: ", "colseparator"); - output_c_string(p->out, p->colSeparator); - raw_printf(p->out, "\n"); - utf8_printf(p->out,"%12.12s: ", "rowseparator"); - output_c_string(p->out, p->rowSeparator); - raw_printf(p->out, "\n"); - switch( p->statsOn ){ - case 0: zOut = "off"; break; - default: zOut = "on"; break; - case 2: zOut = "stmt"; break; - case 3: zOut = "vmstep"; break; - } - utf8_printf(p->out, "%12.12s: %s\n","stats", zOut); - utf8_printf(p->out, "%12.12s: ", "width"); - for (i=0;inWidth;i++) { - raw_printf(p->out, "%d ", p->colWidth[i]); - } - raw_printf(p->out, "\n"); - utf8_printf(p->out, "%12.12s: %s\n", "filename", - p->pAuxDb->zDbFilename ? p->pAuxDb->zDbFilename : ""); - }else - - if( c=='s' && strncmp(azArg[0], "stats", n)==0 ){ - if( nArg==2 ){ - if( strcmp(azArg[1],"stmt")==0 ){ - p->statsOn = 2; - }else if( strcmp(azArg[1],"vmstep")==0 ){ - p->statsOn = 3; - }else{ - p->statsOn = (u8)booleanValue(azArg[1]); - } - }else if( nArg==1 ){ - display_stats(p->db, p, 0); - }else{ - raw_printf(stderr, "Usage: .stats ?on|off|stmt|vmstep?\n"); - rc = 1; - } - }else - - if( (c=='t' && n>1 && strncmp(azArg[0], "tables", n)==0) - || (c=='i' && (strncmp(azArg[0], "indices", n)==0 - || strncmp(azArg[0], "indexes", n)==0) ) - ){ - sqlite3_stmt *pStmt; - char **azResult; - int nRow, nAlloc; - int ii; - ShellText s; - initText(&s); - open_db(p, 0); - rc = sqlite3_prepare_v2(p->db, "PRAGMA database_list", -1, &pStmt, 0); - if( rc ){ - sqlite3_finalize(pStmt); - return shellDatabaseError(p->db); - } - - if( nArg>2 && c=='i' ){ - /* It is an historical accident that the .indexes command shows an error + if( c=='s' && strncmp(azArg[0], "show", n)==0 ){ + static const char *azBool[] = { "off", "on", "trigger", "full"}; + const char *zOut; + int i; + if( nArg!=1 ){ + raw_printf(stderr, "Usage: .show\n"); + rc = 1; + goto meta_command_exit; + } + utf8_printf(p->out, "%12.12s: %s\n","echo", + azBool[ShellHasFlag(p, SHFLG_Echo)]); + utf8_printf(p->out, "%12.12s: %s\n","eqp", azBool[p->autoEQP&3]); + utf8_printf(p->out, "%12.12s: %s\n","explain", + p->mode==MODE_Explain ? "on" : p->autoExplain ? "auto" : "off"); + utf8_printf(p->out,"%12.12s: %s\n","headers", azBool[p->showHeader!=0]); + utf8_printf(p->out, "%12.12s: %s\n","mode", modeDescr[p->mode]); + utf8_printf(p->out, "%12.12s: ", "nullvalue"); + output_c_string(p->out, p->nullValue); + raw_printf(p->out, "\n"); + utf8_printf(p->out,"%12.12s: %s\n","output", + strlen30(p->outfile) ? p->outfile : "stdout"); + utf8_printf(p->out,"%12.12s: ", "colseparator"); + output_c_string(p->out, p->colSeparator); + raw_printf(p->out, "\n"); + utf8_printf(p->out,"%12.12s: ", "rowseparator"); + output_c_string(p->out, p->rowSeparator); + raw_printf(p->out, "\n"); + switch( p->statsOn ){ + case 0: zOut = "off"; break; + default: zOut = "on"; break; + case 2: zOut = "stmt"; break; + case 3: zOut = "vmstep"; break; + } + utf8_printf(p->out, "%12.12s: %s\n","stats", zOut); + utf8_printf(p->out, "%12.12s: ", "width"); + for (i=0;inWidth;i++) { + raw_printf(p->out, "%d ", p->colWidth[i]); + } + raw_printf(p->out, "\n"); + utf8_printf(p->out, "%12.12s: %s\n", "filename", + p->pAuxDb->zDbFilename ? p->pAuxDb->zDbFilename : ""); + }else + + if( c=='s' && strncmp(azArg[0], "stats", n)==0 ){ + if( nArg==2 ){ + if( strcmp(azArg[1],"stmt")==0 ){ + p->statsOn = 2; + }else if( strcmp(azArg[1],"vmstep")==0 ){ + p->statsOn = 3; + }else{ + p->statsOn = (u8)booleanValue(azArg[1]); + } + }else if( nArg==1 ){ + display_stats(p->db, p, 0); + }else{ + raw_printf(stderr, "Usage: .stats ?on|off|stmt|vmstep?\n"); + rc = 1; + } + }else + + if( (c=='t' && n>1 && strncmp(azArg[0], "tables", n)==0) + || (c=='i' && (strncmp(azArg[0], "indices", n)==0 + || strncmp(azArg[0], "indexes", n)==0) ) + ){ + sqlite3_stmt *pStmt; + char **azResult; + int nRow, nAlloc; + int ii; + ShellText s; + initText(&s); + open_db(p, 0); + rc = sqlite3_prepare_v2(p->db, "PRAGMA database_list", -1, &pStmt, 0); + if( rc ){ + sqlite3_finalize(pStmt); + return shellDatabaseError(p->db); + } + + if( nArg>2 && c=='i' ){ + /* It is an historical accident that the .indexes command shows an error ** when called with the wrong number of arguments whereas the .tables ** command does not. */ - raw_printf(stderr, "Usage: .indexes ?LIKE-PATTERN?\n"); - rc = 1; - sqlite3_finalize(pStmt); - goto meta_command_exit; - } - for(ii=0; sqlite3_step(pStmt)==SQLITE_ROW; ii++){ - const char *zDbName = (const char*)sqlite3_column_text(pStmt, 1); - if( zDbName==0 ) continue; - if( s.z && s.z[0] ) appendText(&s, " UNION ALL ", 0); - if( sqlite3_stricmp(zDbName, "main")==0 ){ - appendText(&s, "SELECT name FROM ", 0); - }else{ - appendText(&s, "SELECT ", 0); - appendText(&s, zDbName, '\''); - appendText(&s, "||'.'||name FROM ", 0); - } - appendText(&s, zDbName, '"'); - appendText(&s, ".sqlite_schema ", 0); - if( c=='t' ){ - appendText(&s," WHERE type IN ('table','view')" - " AND name NOT LIKE 'sqlite_%'" - " AND name LIKE ?1", 0); - }else{ - appendText(&s," WHERE type='index'" - " AND tbl_name LIKE ?1", 0); - } - } - rc = sqlite3_finalize(pStmt); - if( rc==SQLITE_OK ){ - appendText(&s, " ORDER BY 1", 0); - rc = sqlite3_prepare_v2(p->db, s.z, -1, &pStmt, 0); - } - freeText(&s); - if( rc ) return shellDatabaseError(p->db); - - /* Run the SQL statement prepared by the above block. Store the results + raw_printf(stderr, "Usage: .indexes ?LIKE-PATTERN?\n"); + rc = 1; + sqlite3_finalize(pStmt); + goto meta_command_exit; + } + for(ii=0; sqlite3_step(pStmt)==SQLITE_ROW; ii++){ + const char *zDbName = (const char*)sqlite3_column_text(pStmt, 1); + if( zDbName==0 ) continue; + if( s.z && s.z[0] ) appendText(&s, " UNION ALL ", 0); + if( sqlite3_stricmp(zDbName, "main")==0 ){ + appendText(&s, "SELECT name FROM ", 0); + }else{ + appendText(&s, "SELECT ", 0); + appendText(&s, zDbName, '\''); + appendText(&s, "||'.'||name FROM ", 0); + } + appendText(&s, zDbName, '"'); + appendText(&s, ".sqlite_schema ", 0); + if( c=='t' ){ + appendText(&s," WHERE type IN ('table','view')" + " AND name NOT LIKE 'sqlite_%'" + " AND name LIKE ?1", 0); + }else{ + appendText(&s," WHERE type='index'" + " AND tbl_name LIKE ?1", 0); + } + } + rc = sqlite3_finalize(pStmt); + if( rc==SQLITE_OK ){ + appendText(&s, " ORDER BY 1", 0); + rc = sqlite3_prepare_v2(p->db, s.z, -1, &pStmt, 0); + } + freeText(&s); + if( rc ) return shellDatabaseError(p->db); + + /* Run the SQL statement prepared by the above block. Store the results ** as an array of nul-terminated strings in azResult[]. */ - nRow = nAlloc = 0; - azResult = 0; - if( nArg>1 ){ - sqlite3_bind_text(pStmt, 1, azArg[1], -1, SQLITE_TRANSIENT); - }else{ - sqlite3_bind_text(pStmt, 1, "%", -1, SQLITE_STATIC); - } - while( sqlite3_step(pStmt)==SQLITE_ROW ){ - if( nRow>=nAlloc ){ - char **azNew; - int n2 = nAlloc*2 + 10; - azNew = sqlite3_realloc64(azResult, sizeof(azResult[0])*n2); - if( azNew==0 ) shell_out_of_memory(); - nAlloc = n2; - azResult = azNew; - } - azResult[nRow] = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 0)); - if( 0==azResult[nRow] ) shell_out_of_memory(); - nRow++; - } - if( sqlite3_finalize(pStmt)!=SQLITE_OK ){ - rc = shellDatabaseError(p->db); - } - - /* Pretty-print the contents of array azResult[] to the output */ - if( rc==0 && nRow>0 ){ - int len, maxlen = 0; - int i, j; - int nPrintCol, nPrintRow; - for(i=0; imaxlen ) maxlen = len; - } - nPrintCol = 80/(maxlen+2); - if( nPrintCol<1 ) nPrintCol = 1; - nPrintRow = (nRow + nPrintCol - 1)/nPrintCol; - for(i=0; iout, "%s%-*s", zSp, maxlen, - azResult[j] ? azResult[j]:""); - } - raw_printf(p->out, "\n"); - } - } - - for(ii=0; iiout = output_file_open("testcase-out.txt", 0); - if( p->out==0 ){ - raw_printf(stderr, "Error: cannot open 'testcase-out.txt'\n"); - } - if( nArg>=2 ){ - sqlite3_snprintf(sizeof(p->zTestcase), p->zTestcase, "%s", azArg[1]); - }else{ - sqlite3_snprintf(sizeof(p->zTestcase), p->zTestcase, "?"); - } - }else + nRow = nAlloc = 0; + azResult = 0; + if( nArg>1 ){ + sqlite3_bind_text(pStmt, 1, azArg[1], -1, SQLITE_TRANSIENT); + }else{ + sqlite3_bind_text(pStmt, 1, "%", -1, SQLITE_STATIC); + } + while( sqlite3_step(pStmt)==SQLITE_ROW ){ + if( nRow>=nAlloc ){ + char **azNew; + int n2 = nAlloc*2 + 10; + azNew = sqlite3_realloc64(azResult, sizeof(azResult[0])*n2); + if( azNew==0 ) shell_out_of_memory(); + nAlloc = n2; + azResult = azNew; + } + azResult[nRow] = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 0)); + if( 0==azResult[nRow] ) shell_out_of_memory(); + nRow++; + } + if( sqlite3_finalize(pStmt)!=SQLITE_OK ){ + rc = shellDatabaseError(p->db); + } + + /* Pretty-print the contents of array azResult[] to the output */ + if( rc==0 && nRow>0 ){ + int len, maxlen = 0; + int i, j; + int nPrintCol, nPrintRow; + for(i=0; imaxlen ) maxlen = len; + } + nPrintCol = 80/(maxlen+2); + if( nPrintCol<1 ) nPrintCol = 1; + nPrintRow = (nRow + nPrintCol - 1)/nPrintCol; + for(i=0; iout, "%s%-*s", zSp, maxlen, + azResult[j] ? azResult[j]:""); + } + raw_printf(p->out, "\n"); + } + } + + for(ii=0; iiout = output_file_open("testcase-out.txt", 0); + if( p->out==0 ){ + raw_printf(stderr, "Error: cannot open 'testcase-out.txt'\n"); + } + if( nArg>=2 ){ + sqlite3_snprintf(sizeof(p->zTestcase), p->zTestcase, "%s", azArg[1]); + }else{ + sqlite3_snprintf(sizeof(p->zTestcase), p->zTestcase, "?"); + } + }else #ifndef SQLITE_UNTESTABLE - if( c=='t' && n>=8 && strncmp(azArg[0], "testctrl", n)==0 ){ - static const struct { - const char *zCtrlName; /* Name of a test-control option */ - int ctrlCode; /* Integer code for that option */ - int unSafe; /* Not valid for --safe mode */ - const char *zUsage; /* Usage notes */ - } aCtrl[] = { - { "always", SQLITE_TESTCTRL_ALWAYS, 1, "BOOLEAN" }, - { "assert", SQLITE_TESTCTRL_ASSERT, 1, "BOOLEAN" }, - /*{ "benign_malloc_hooks",SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS,1, "" },*/ - /*{ "bitvec_test", SQLITE_TESTCTRL_BITVEC_TEST, 1, "" },*/ - { "byteorder", SQLITE_TESTCTRL_BYTEORDER, 0, "" }, - { "extra_schema_checks",SQLITE_TESTCTRL_EXTRA_SCHEMA_CHECKS,0,"BOOLEAN" }, - /*{ "fault_install", SQLITE_TESTCTRL_FAULT_INSTALL, 1,"" },*/ - { "imposter", SQLITE_TESTCTRL_IMPOSTER,1,"SCHEMA ON/OFF ROOTPAGE"}, - { "internal_functions", SQLITE_TESTCTRL_INTERNAL_FUNCTIONS,0,"" }, - { "localtime_fault", SQLITE_TESTCTRL_LOCALTIME_FAULT,0,"BOOLEAN" }, - { "never_corrupt", SQLITE_TESTCTRL_NEVER_CORRUPT,1, "BOOLEAN" }, - { "optimizations", SQLITE_TESTCTRL_OPTIMIZATIONS,0,"DISABLE-MASK" }, + if( c=='t' && n>=8 && strncmp(azArg[0], "testctrl", n)==0 ){ + static const struct { + const char *zCtrlName; /* Name of a test-control option */ + int ctrlCode; /* Integer code for that option */ + int unSafe; /* Not valid for --safe mode */ + const char *zUsage; /* Usage notes */ + } aCtrl[] = { + { "always", SQLITE_TESTCTRL_ALWAYS, 1, "BOOLEAN" }, + { "assert", SQLITE_TESTCTRL_ASSERT, 1, "BOOLEAN" }, + /*{ "benign_malloc_hooks",SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS,1, "" },*/ + /*{ "bitvec_test", SQLITE_TESTCTRL_BITVEC_TEST, 1, "" },*/ + { "byteorder", SQLITE_TESTCTRL_BYTEORDER, 0, "" }, + { "extra_schema_checks",SQLITE_TESTCTRL_EXTRA_SCHEMA_CHECKS,0,"BOOLEAN" }, + /*{ "fault_install", SQLITE_TESTCTRL_FAULT_INSTALL, 1,"" },*/ + { "imposter", SQLITE_TESTCTRL_IMPOSTER,1,"SCHEMA ON/OFF ROOTPAGE"}, + { "internal_functions", SQLITE_TESTCTRL_INTERNAL_FUNCTIONS,0,"" }, + { "localtime_fault", SQLITE_TESTCTRL_LOCALTIME_FAULT,0,"BOOLEAN" }, + { "never_corrupt", SQLITE_TESTCTRL_NEVER_CORRUPT,1, "BOOLEAN" }, + { "optimizations", SQLITE_TESTCTRL_OPTIMIZATIONS,0,"DISABLE-MASK" }, #ifdef YYCOVERAGE - { "parser_coverage", SQLITE_TESTCTRL_PARSER_COVERAGE,0,"" }, + { "parser_coverage", SQLITE_TESTCTRL_PARSER_COVERAGE,0,"" }, #endif - { "pending_byte", SQLITE_TESTCTRL_PENDING_BYTE,0, "OFFSET " }, - { "prng_restore", SQLITE_TESTCTRL_PRNG_RESTORE,0, "" }, - { "prng_save", SQLITE_TESTCTRL_PRNG_SAVE, 0, "" }, - { "prng_seed", SQLITE_TESTCTRL_PRNG_SEED, 0, "SEED ?db?" }, - { "seek_count", SQLITE_TESTCTRL_SEEK_COUNT, 0, "" }, - { "sorter_mmap", SQLITE_TESTCTRL_SORTER_MMAP, 0, "NMAX" }, - { "tune", SQLITE_TESTCTRL_TUNE, 1, "ID VALUE" }, - }; - int testctrl = -1; - int iCtrl = -1; - int rc2 = 0; /* 0: usage. 1: %d 2: %x 3: no-output */ - int isOk = 0; - int i, n2; - const char *zCmd = 0; - - open_db(p, 0); - zCmd = nArg>=2 ? azArg[1] : "help"; - - /* The argument can optionally begin with "-" or "--" */ - if( zCmd[0]=='-' && zCmd[1] ){ - zCmd++; - if( zCmd[0]=='-' && zCmd[1] ) zCmd++; - } - - /* --help lists all test-controls */ - if( strcmp(zCmd,"help")==0 ){ - utf8_printf(p->out, "Available test-controls:\n"); - for(i=0; iout, " .testctrl %s %s\n", - aCtrl[i].zCtrlName, aCtrl[i].zUsage); - } - rc = 1; - goto meta_command_exit; - } - - /* convert testctrl text option to value. allow any unique prefix + { "pending_byte", SQLITE_TESTCTRL_PENDING_BYTE,0, "OFFSET " }, + { "prng_restore", SQLITE_TESTCTRL_PRNG_RESTORE,0, "" }, + { "prng_save", SQLITE_TESTCTRL_PRNG_SAVE, 0, "" }, + { "prng_seed", SQLITE_TESTCTRL_PRNG_SEED, 0, "SEED ?db?" }, + { "seek_count", SQLITE_TESTCTRL_SEEK_COUNT, 0, "" }, + { "sorter_mmap", SQLITE_TESTCTRL_SORTER_MMAP, 0, "NMAX" }, + { "tune", SQLITE_TESTCTRL_TUNE, 1, "ID VALUE" }, + }; + int testctrl = -1; + int iCtrl = -1; + int rc2 = 0; /* 0: usage. 1: %d 2: %x 3: no-output */ + int isOk = 0; + int i, n2; + const char *zCmd = 0; + + open_db(p, 0); + zCmd = nArg>=2 ? azArg[1] : "help"; + + /* The argument can optionally begin with "-" or "--" */ + if( zCmd[0]=='-' && zCmd[1] ){ + zCmd++; + if( zCmd[0]=='-' && zCmd[1] ) zCmd++; + } + + /* --help lists all test-controls */ + if( strcmp(zCmd,"help")==0 ){ + utf8_printf(p->out, "Available test-controls:\n"); + for(i=0; iout, " .testctrl %s %s\n", + aCtrl[i].zCtrlName, aCtrl[i].zUsage); + } + rc = 1; + goto meta_command_exit; + } + + /* convert testctrl text option to value. allow any unique prefix ** of the option name, or a numerical value. */ - n2 = strlen30(zCmd); - for(i=0; ibSafeMode ){ - utf8_printf(stderr, - "line %d: \".testctrl %s\" may not be used in safe mode\n", - p->lineno, aCtrl[iCtrl].zCtrlName); - exit(1); - }else{ - switch(testctrl){ - - /* sqlite3_test_control(int, db, int) */ - case SQLITE_TESTCTRL_OPTIMIZATIONS: - if( nArg==3 ){ - unsigned int opt = (unsigned int)strtol(azArg[2], 0, 0); - rc2 = sqlite3_test_control(testctrl, p->db, opt); - isOk = 3; - } - break; - - /* sqlite3_test_control(int) */ - case SQLITE_TESTCTRL_PRNG_SAVE: - case SQLITE_TESTCTRL_PRNG_RESTORE: - case SQLITE_TESTCTRL_BYTEORDER: - if( nArg==2 ){ - rc2 = sqlite3_test_control(testctrl); - isOk = testctrl==SQLITE_TESTCTRL_BYTEORDER ? 1 : 3; - } - break; - - /* sqlite3_test_control(int, uint) */ - case SQLITE_TESTCTRL_PENDING_BYTE: - if( nArg==3 ){ - unsigned int opt = (unsigned int)integerValue(azArg[2]); - rc2 = sqlite3_test_control(testctrl, opt); - isOk = 3; - } - break; - - /* sqlite3_test_control(int, int, sqlite3*) */ - case SQLITE_TESTCTRL_PRNG_SEED: - if( nArg==3 || nArg==4 ){ - int ii = (int)integerValue(azArg[2]); - sqlite3 *db; - if( ii==0 && strcmp(azArg[2],"random")==0 ){ - sqlite3_randomness(sizeof(ii),&ii); - printf("-- random seed: %d\n", ii); - } - if( nArg==3 ){ - db = 0; - }else{ - db = p->db; - /* Make sure the schema has been loaded */ - sqlite3_table_column_metadata(db, 0, "x", 0, 0, 0, 0, 0, 0); - } - rc2 = sqlite3_test_control(testctrl, ii, db); - isOk = 3; - } - break; - - /* sqlite3_test_control(int, int) */ - case SQLITE_TESTCTRL_ASSERT: - case SQLITE_TESTCTRL_ALWAYS: - if( nArg==3 ){ - int opt = booleanValue(azArg[2]); - rc2 = sqlite3_test_control(testctrl, opt); - isOk = 1; - } - break; - - /* sqlite3_test_control(int, int) */ - case SQLITE_TESTCTRL_LOCALTIME_FAULT: - case SQLITE_TESTCTRL_NEVER_CORRUPT: - if( nArg==3 ){ - int opt = booleanValue(azArg[2]); - rc2 = sqlite3_test_control(testctrl, opt); - isOk = 3; - } - break; - - /* sqlite3_test_control(sqlite3*) */ - case SQLITE_TESTCTRL_INTERNAL_FUNCTIONS: - rc2 = sqlite3_test_control(testctrl, p->db); - isOk = 3; - break; - - case SQLITE_TESTCTRL_IMPOSTER: - if( nArg==5 ){ - rc2 = sqlite3_test_control(testctrl, p->db, - azArg[2], - integerValue(azArg[3]), - integerValue(azArg[4])); - isOk = 3; - } - break; - - case SQLITE_TESTCTRL_SEEK_COUNT: { - u64 x = 0; - rc2 = sqlite3_test_control(testctrl, p->db, &x); - utf8_printf(p->out, "%llu\n", x); - isOk = 3; - break; - } + n2 = strlen30(zCmd); + for(i=0; ibSafeMode ){ + utf8_printf(stderr, + "line %d: \".testctrl %s\" may not be used in safe mode\n", + p->lineno, aCtrl[iCtrl].zCtrlName); + exit(1); + }else{ + switch(testctrl){ + + /* sqlite3_test_control(int, db, int) */ + case SQLITE_TESTCTRL_OPTIMIZATIONS: + if( nArg==3 ){ + unsigned int opt = (unsigned int)strtol(azArg[2], 0, 0); + rc2 = sqlite3_test_control(testctrl, p->db, opt); + isOk = 3; + } + break; + + /* sqlite3_test_control(int) */ + case SQLITE_TESTCTRL_PRNG_SAVE: + case SQLITE_TESTCTRL_PRNG_RESTORE: + case SQLITE_TESTCTRL_BYTEORDER: + if( nArg==2 ){ + rc2 = sqlite3_test_control(testctrl); + isOk = testctrl==SQLITE_TESTCTRL_BYTEORDER ? 1 : 3; + } + break; + + /* sqlite3_test_control(int, uint) */ + case SQLITE_TESTCTRL_PENDING_BYTE: + if( nArg==3 ){ + unsigned int opt = (unsigned int)integerValue(azArg[2]); + rc2 = sqlite3_test_control(testctrl, opt); + isOk = 3; + } + break; + + /* sqlite3_test_control(int, int, sqlite3*) */ + case SQLITE_TESTCTRL_PRNG_SEED: + if( nArg==3 || nArg==4 ){ + int ii = (int)integerValue(azArg[2]); + sqlite3 *db; + if( ii==0 && strcmp(azArg[2],"random")==0 ){ + sqlite3_randomness(sizeof(ii),&ii); + printf("-- random seed: %d\n", ii); + } + if( nArg==3 ){ + db = 0; + }else{ + db = p->db; + /* Make sure the schema has been loaded */ + sqlite3_table_column_metadata(db, 0, "x", 0, 0, 0, 0, 0, 0); + } + rc2 = sqlite3_test_control(testctrl, ii, db); + isOk = 3; + } + break; + + /* sqlite3_test_control(int, int) */ + case SQLITE_TESTCTRL_ASSERT: + case SQLITE_TESTCTRL_ALWAYS: + if( nArg==3 ){ + int opt = booleanValue(azArg[2]); + rc2 = sqlite3_test_control(testctrl, opt); + isOk = 1; + } + break; + + /* sqlite3_test_control(int, int) */ + case SQLITE_TESTCTRL_LOCALTIME_FAULT: + case SQLITE_TESTCTRL_NEVER_CORRUPT: + if( nArg==3 ){ + int opt = booleanValue(azArg[2]); + rc2 = sqlite3_test_control(testctrl, opt); + isOk = 3; + } + break; + + /* sqlite3_test_control(sqlite3*) */ + case SQLITE_TESTCTRL_INTERNAL_FUNCTIONS: + rc2 = sqlite3_test_control(testctrl, p->db); + isOk = 3; + break; + + case SQLITE_TESTCTRL_IMPOSTER: + if( nArg==5 ){ + rc2 = sqlite3_test_control(testctrl, p->db, + azArg[2], + integerValue(azArg[3]), + integerValue(azArg[4])); + isOk = 3; + } + break; + + case SQLITE_TESTCTRL_SEEK_COUNT: { + u64 x = 0; + rc2 = sqlite3_test_control(testctrl, p->db, &x); + utf8_printf(p->out, "%llu\n", x); + isOk = 3; + break; + } #ifdef YYCOVERAGE - case SQLITE_TESTCTRL_PARSER_COVERAGE: { - if( nArg==2 ){ - sqlite3_test_control(testctrl, p->out); - isOk = 3; - } - break; - } + case SQLITE_TESTCTRL_PARSER_COVERAGE: { + if( nArg==2 ){ + sqlite3_test_control(testctrl, p->out); + isOk = 3; + } + break; + } #endif #ifdef SQLITE_DEBUG - case SQLITE_TESTCTRL_TUNE: { - if( nArg==4 ){ - int id = (int)integerValue(azArg[2]); - int val = (int)integerValue(azArg[3]); - sqlite3_test_control(testctrl, id, &val); - isOk = 3; - }else if( nArg==3 ){ - int id = (int)integerValue(azArg[2]); - sqlite3_test_control(testctrl, -id, &rc2); - isOk = 1; - }else if( nArg==2 ){ - int id = 1; - while(1){ - int val = 0; - rc2 = sqlite3_test_control(testctrl, -id, &val); - if( rc2!=SQLITE_OK ) break; - if( id>1 ) utf8_printf(p->out, " "); - utf8_printf(p->out, "%d: %d", id, val); - id++; - } - if( id>1 ) utf8_printf(p->out, "\n"); - isOk = 3; - } - break; - } + case SQLITE_TESTCTRL_TUNE: { + if( nArg==4 ){ + int id = (int)integerValue(azArg[2]); + int val = (int)integerValue(azArg[3]); + sqlite3_test_control(testctrl, id, &val); + isOk = 3; + }else if( nArg==3 ){ + int id = (int)integerValue(azArg[2]); + sqlite3_test_control(testctrl, -id, &rc2); + isOk = 1; + }else if( nArg==2 ){ + int id = 1; + while(1){ + int val = 0; + rc2 = sqlite3_test_control(testctrl, -id, &val); + if( rc2!=SQLITE_OK ) break; + if( id>1 ) utf8_printf(p->out, " "); + utf8_printf(p->out, "%d: %d", id, val); + id++; + } + if( id>1 ) utf8_printf(p->out, "\n"); + isOk = 3; + } + break; + } #endif - case SQLITE_TESTCTRL_SORTER_MMAP: - if( nArg==3 ){ - int opt = (unsigned int)integerValue(azArg[2]); - rc2 = sqlite3_test_control(testctrl, p->db, opt); - isOk = 3; - } - break; - } - } - if( isOk==0 && iCtrl>=0 ){ - utf8_printf(p->out, "Usage: .testctrl %s %s\n", zCmd,aCtrl[iCtrl].zUsage); - rc = 1; - }else if( isOk==1 ){ - raw_printf(p->out, "%d\n", rc2); - }else if( isOk==2 ){ - raw_printf(p->out, "0x%08x\n", rc2); - } - }else + case SQLITE_TESTCTRL_SORTER_MMAP: + if( nArg==3 ){ + int opt = (unsigned int)integerValue(azArg[2]); + rc2 = sqlite3_test_control(testctrl, p->db, opt); + isOk = 3; + } + break; + } + } + if( isOk==0 && iCtrl>=0 ){ + utf8_printf(p->out, "Usage: .testctrl %s %s\n", zCmd,aCtrl[iCtrl].zUsage); + rc = 1; + }else if( isOk==1 ){ + raw_printf(p->out, "%d\n", rc2); + }else if( isOk==2 ){ + raw_printf(p->out, "0x%08x\n", rc2); + } + }else #endif /* !defined(SQLITE_UNTESTABLE) */ - if( c=='t' && n>4 && strncmp(azArg[0], "timeout", n)==0 ){ - open_db(p, 0); - sqlite3_busy_timeout(p->db, nArg>=2 ? (int)integerValue(azArg[1]) : 0); - }else - - if( c=='t' && n>=5 && strncmp(azArg[0], "timer", n)==0 ){ - if( nArg==2 ){ - enableTimer = booleanValue(azArg[1]); - if( enableTimer && !HAS_TIMER ){ - raw_printf(stderr, "Error: timer not available on this system.\n"); - enableTimer = 0; - } - }else{ - raw_printf(stderr, "Usage: .timer on|off\n"); - rc = 1; - } - }else + if( c=='t' && n>4 && strncmp(azArg[0], "timeout", n)==0 ){ + open_db(p, 0); + sqlite3_busy_timeout(p->db, nArg>=2 ? (int)integerValue(azArg[1]) : 0); + }else + + if( c=='t' && n>=5 && strncmp(azArg[0], "timer", n)==0 ){ + if( nArg==2 ){ + enableTimer = booleanValue(azArg[1]); + if( enableTimer && !HAS_TIMER ){ + raw_printf(stderr, "Error: timer not available on this system.\n"); + enableTimer = 0; + } + }else{ + raw_printf(stderr, "Usage: .timer on|off\n"); + rc = 1; + } + }else #ifndef SQLITE_OMIT_TRACE - if( c=='t' && strncmp(azArg[0], "trace", n)==0 ){ - int mType = 0; - int jj; - open_db(p, 0); - for(jj=1; jjeTraceType = SHELL_TRACE_EXPANDED; - } + if( c=='t' && strncmp(azArg[0], "trace", n)==0 ){ + int mType = 0; + int jj; + open_db(p, 0); + for(jj=1; jjeTraceType = SHELL_TRACE_EXPANDED; + } #ifdef SQLITE_ENABLE_NORMALIZE - else if( optionMatch(z, "normalized") ){ - p->eTraceType = SHELL_TRACE_NORMALIZED; - } + else if( optionMatch(z, "normalized") ){ + p->eTraceType = SHELL_TRACE_NORMALIZED; + } #endif - else if( optionMatch(z, "plain") ){ - p->eTraceType = SHELL_TRACE_PLAIN; - } - else if( optionMatch(z, "profile") ){ - mType |= SQLITE_TRACE_PROFILE; - } - else if( optionMatch(z, "row") ){ - mType |= SQLITE_TRACE_ROW; - } - else if( optionMatch(z, "stmt") ){ - mType |= SQLITE_TRACE_STMT; - } - else if( optionMatch(z, "close") ){ - mType |= SQLITE_TRACE_CLOSE; - } - else { - raw_printf(stderr, "Unknown option \"%s\" on \".trace\"\n", z); - rc = 1; - goto meta_command_exit; - } - }else{ - output_file_close(p->traceOut); - p->traceOut = output_file_open(azArg[1], 0); - } - } - if( p->traceOut==0 ){ - sqlite3_trace_v2(p->db, 0, 0, 0); - }else{ - if( mType==0 ) mType = SQLITE_TRACE_STMT; - sqlite3_trace_v2(p->db, mType, sql_trace_callback, p); - } - }else + else if( optionMatch(z, "plain") ){ + p->eTraceType = SHELL_TRACE_PLAIN; + } + else if( optionMatch(z, "profile") ){ + mType |= SQLITE_TRACE_PROFILE; + } + else if( optionMatch(z, "row") ){ + mType |= SQLITE_TRACE_ROW; + } + else if( optionMatch(z, "stmt") ){ + mType |= SQLITE_TRACE_STMT; + } + else if( optionMatch(z, "close") ){ + mType |= SQLITE_TRACE_CLOSE; + } + else { + raw_printf(stderr, "Unknown option \"%s\" on \".trace\"\n", z); + rc = 1; + goto meta_command_exit; + } + }else{ + output_file_close(p->traceOut); + p->traceOut = output_file_open(azArg[1], 0); + } + } + if( p->traceOut==0 ){ + sqlite3_trace_v2(p->db, 0, 0, 0); + }else{ + if( mType==0 ) mType = SQLITE_TRACE_STMT; + sqlite3_trace_v2(p->db, mType, sql_trace_callback, p); + } + }else #endif /* !defined(SQLITE_OMIT_TRACE) */ #if defined(SQLITE_DEBUG) && !defined(SQLITE_OMIT_VIRTUALTABLE) - if( c=='u' && strncmp(azArg[0], "unmodule", n)==0 ){ - int ii; - int lenOpt; - char *zOpt; - if( nArg<2 ){ - raw_printf(stderr, "Usage: .unmodule [--allexcept] NAME ...\n"); - rc = 1; - goto meta_command_exit; - } - open_db(p, 0); - zOpt = azArg[1]; - if( zOpt[0]=='-' && zOpt[1]=='-' && zOpt[2]!=0 ) zOpt++; - lenOpt = (int)strlen(zOpt); - if( lenOpt>=3 && strncmp(zOpt, "-allexcept",lenOpt)==0 ){ - assert( azArg[nArg]==0 ); - sqlite3_drop_modules(p->db, nArg>2 ? (const char**)(azArg+2) : 0); - }else{ - for(ii=1; iidb, azArg[ii], 0, 0); - } - } - }else + if( c=='u' && strncmp(azArg[0], "unmodule", n)==0 ){ + int ii; + int lenOpt; + char *zOpt; + if( nArg<2 ){ + raw_printf(stderr, "Usage: .unmodule [--allexcept] NAME ...\n"); + rc = 1; + goto meta_command_exit; + } + open_db(p, 0); + zOpt = azArg[1]; + if( zOpt[0]=='-' && zOpt[1]=='-' && zOpt[2]!=0 ) zOpt++; + lenOpt = (int)strlen(zOpt); + if( lenOpt>=3 && strncmp(zOpt, "-allexcept",lenOpt)==0 ){ + assert( azArg[nArg]==0 ); + sqlite3_drop_modules(p->db, nArg>2 ? (const char**)(azArg+2) : 0); + }else{ + for(ii=1; iidb, azArg[ii], 0, 0); + } + } + }else #endif #if SQLITE_USER_AUTHENTICATION - if( c=='u' && strncmp(azArg[0], "user", n)==0 ){ - if( nArg<2 ){ - raw_printf(stderr, "Usage: .user SUBCOMMAND ...\n"); - rc = 1; - goto meta_command_exit; - } - open_db(p, 0); - if( strcmp(azArg[1],"login")==0 ){ - if( nArg!=4 ){ - raw_printf(stderr, "Usage: .user login USER PASSWORD\n"); - rc = 1; - goto meta_command_exit; - } - rc = sqlite3_user_authenticate(p->db, azArg[2], azArg[3], - strlen30(azArg[3])); - if( rc ){ - utf8_printf(stderr, "Authentication failed for user %s\n", azArg[2]); - rc = 1; - } - }else if( strcmp(azArg[1],"add")==0 ){ - if( nArg!=5 ){ - raw_printf(stderr, "Usage: .user add USER PASSWORD ISADMIN\n"); - rc = 1; - goto meta_command_exit; - } - rc = sqlite3_user_add(p->db, azArg[2], azArg[3], strlen30(azArg[3]), - booleanValue(azArg[4])); - if( rc ){ - raw_printf(stderr, "User-Add failed: %d\n", rc); - rc = 1; - } - }else if( strcmp(azArg[1],"edit")==0 ){ - if( nArg!=5 ){ - raw_printf(stderr, "Usage: .user edit USER PASSWORD ISADMIN\n"); - rc = 1; - goto meta_command_exit; - } - rc = sqlite3_user_change(p->db, azArg[2], azArg[3], strlen30(azArg[3]), - booleanValue(azArg[4])); - if( rc ){ - raw_printf(stderr, "User-Edit failed: %d\n", rc); - rc = 1; - } - }else if( strcmp(azArg[1],"delete")==0 ){ - if( nArg!=3 ){ - raw_printf(stderr, "Usage: .user delete USER\n"); - rc = 1; - goto meta_command_exit; - } - rc = sqlite3_user_delete(p->db, azArg[2]); - if( rc ){ - raw_printf(stderr, "User-Delete failed: %d\n", rc); - rc = 1; - } - }else{ - raw_printf(stderr, "Usage: .user login|add|edit|delete ...\n"); - rc = 1; - goto meta_command_exit; - } - }else + if( c=='u' && strncmp(azArg[0], "user", n)==0 ){ + if( nArg<2 ){ + raw_printf(stderr, "Usage: .user SUBCOMMAND ...\n"); + rc = 1; + goto meta_command_exit; + } + open_db(p, 0); + if( strcmp(azArg[1],"login")==0 ){ + if( nArg!=4 ){ + raw_printf(stderr, "Usage: .user login USER PASSWORD\n"); + rc = 1; + goto meta_command_exit; + } + rc = sqlite3_user_authenticate(p->db, azArg[2], azArg[3], + strlen30(azArg[3])); + if( rc ){ + utf8_printf(stderr, "Authentication failed for user %s\n", azArg[2]); + rc = 1; + } + }else if( strcmp(azArg[1],"add")==0 ){ + if( nArg!=5 ){ + raw_printf(stderr, "Usage: .user add USER PASSWORD ISADMIN\n"); + rc = 1; + goto meta_command_exit; + } + rc = sqlite3_user_add(p->db, azArg[2], azArg[3], strlen30(azArg[3]), + booleanValue(azArg[4])); + if( rc ){ + raw_printf(stderr, "User-Add failed: %d\n", rc); + rc = 1; + } + }else if( strcmp(azArg[1],"edit")==0 ){ + if( nArg!=5 ){ + raw_printf(stderr, "Usage: .user edit USER PASSWORD ISADMIN\n"); + rc = 1; + goto meta_command_exit; + } + rc = sqlite3_user_change(p->db, azArg[2], azArg[3], strlen30(azArg[3]), + booleanValue(azArg[4])); + if( rc ){ + raw_printf(stderr, "User-Edit failed: %d\n", rc); + rc = 1; + } + }else if( strcmp(azArg[1],"delete")==0 ){ + if( nArg!=3 ){ + raw_printf(stderr, "Usage: .user delete USER\n"); + rc = 1; + goto meta_command_exit; + } + rc = sqlite3_user_delete(p->db, azArg[2]); + if( rc ){ + raw_printf(stderr, "User-Delete failed: %d\n", rc); + rc = 1; + } + }else{ + raw_printf(stderr, "Usage: .user login|add|edit|delete ...\n"); + rc = 1; + goto meta_command_exit; + } + }else #endif /* SQLITE_USER_AUTHENTICATION */ - if( c=='v' && strncmp(azArg[0], "version", n)==0 ){ - utf8_printf(p->out, "SQLite %s %s\n" /*extra-version-info*/, - sqlite3_libversion(), sqlite3_sourceid()); + if( c=='v' && strncmp(azArg[0], "version", n)==0 ){ + utf8_printf(p->out, "SQLite %s %s\n" /*extra-version-info*/, + sqlite3_libversion(), sqlite3_sourceid()); #if SQLITE_HAVE_ZLIB - utf8_printf(p->out, "zlib version %s\n", zlibVersion()); + utf8_printf(p->out, "zlib version %s\n", zlibVersion()); #endif #define CTIMEOPT_VAL_(opt) #opt #define CTIMEOPT_VAL(opt) CTIMEOPT_VAL_(opt) #if defined(__clang__) && defined(__clang_major__) - utf8_printf(p->out, "clang-" CTIMEOPT_VAL(__clang_major__) "." - CTIMEOPT_VAL(__clang_minor__) "." - CTIMEOPT_VAL(__clang_patchlevel__) "\n"); + utf8_printf(p->out, "clang-" CTIMEOPT_VAL(__clang_major__) "." + CTIMEOPT_VAL(__clang_minor__) "." + CTIMEOPT_VAL(__clang_patchlevel__) "\n"); #elif defined(_MSC_VER) - utf8_printf(p->out, "msvc-" CTIMEOPT_VAL(_MSC_VER) "\n"); + utf8_printf(p->out, "msvc-" CTIMEOPT_VAL(_MSC_VER) "\n"); #elif defined(__GNUC__) && defined(__VERSION__) - utf8_printf(p->out, "gcc-" __VERSION__ "\n"); + utf8_printf(p->out, "gcc-" __VERSION__ "\n"); #endif - }else - - if( c=='v' && strncmp(azArg[0], "vfsinfo", n)==0 ){ - const char *zDbName = nArg==2 ? azArg[1] : "main"; - sqlite3_vfs *pVfs = 0; - if( p->db ){ - sqlite3_file_control(p->db, zDbName, SQLITE_FCNTL_VFS_POINTER, &pVfs); - if( pVfs ){ - utf8_printf(p->out, "vfs.zName = \"%s\"\n", pVfs->zName); - raw_printf(p->out, "vfs.iVersion = %d\n", pVfs->iVersion); - raw_printf(p->out, "vfs.szOsFile = %d\n", pVfs->szOsFile); - raw_printf(p->out, "vfs.mxPathname = %d\n", pVfs->mxPathname); - } - } - }else - - if( c=='v' && strncmp(azArg[0], "vfslist", n)==0 ){ - sqlite3_vfs *pVfs; - sqlite3_vfs *pCurrent = 0; - if( p->db ){ - sqlite3_file_control(p->db, "main", SQLITE_FCNTL_VFS_POINTER, &pCurrent); - } - for(pVfs=sqlite3_vfs_find(0); pVfs; pVfs=pVfs->pNext){ - utf8_printf(p->out, "vfs.zName = \"%s\"%s\n", pVfs->zName, - pVfs==pCurrent ? " <--- CURRENT" : ""); - raw_printf(p->out, "vfs.iVersion = %d\n", pVfs->iVersion); - raw_printf(p->out, "vfs.szOsFile = %d\n", pVfs->szOsFile); - raw_printf(p->out, "vfs.mxPathname = %d\n", pVfs->mxPathname); - if( pVfs->pNext ){ - raw_printf(p->out, "-----------------------------------\n"); - } - } - }else - - if( c=='v' && strncmp(azArg[0], "vfsname", n)==0 ){ - const char *zDbName = nArg==2 ? azArg[1] : "main"; - char *zVfsName = 0; - if( p->db ){ - sqlite3_file_control(p->db, zDbName, SQLITE_FCNTL_VFSNAME, &zVfsName); - if( zVfsName ){ - utf8_printf(p->out, "%s\n", zVfsName); - sqlite3_free(zVfsName); - } - } - }else - - if( c=='w' && strncmp(azArg[0], "wheretrace", n)==0 ){ - unsigned int x = nArg>=2 ? (unsigned int)integerValue(azArg[1]) : 0xffffffff; - sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 3, &x); - }else - - if( c=='w' && strncmp(azArg[0], "width", n)==0 ){ - int j; - assert( nArg<=ArraySize(azArg) ); - p->nWidth = nArg-1; - p->colWidth = realloc(p->colWidth, (p->nWidth+1)*sizeof(int)*2); - if( p->colWidth==0 && p->nWidth>0 ) shell_out_of_memory(); - if( p->nWidth ) p->actualWidth = &p->colWidth[p->nWidth]; - for(j=1; jcolWidth[j-1] = (int)integerValue(azArg[j]); - } - }else - - { - utf8_printf(stderr, "Error: unknown command or invalid arguments: " - " \"%s\". Enter \".help\" for help\n", azArg[0]); - rc = 1; - } + }else -meta_command_exit: - if( p->outCount ){ - p->outCount--; - if( p->outCount==0 ) output_reset(p); + if( c=='v' && strncmp(azArg[0], "vfsinfo", n)==0 ){ + const char *zDbName = nArg==2 ? azArg[1] : "main"; + sqlite3_vfs *pVfs = 0; + if( p->db ){ + sqlite3_file_control(p->db, zDbName, SQLITE_FCNTL_VFS_POINTER, &pVfs); + if( pVfs ){ + utf8_printf(p->out, "vfs.zName = \"%s\"\n", pVfs->zName); + raw_printf(p->out, "vfs.iVersion = %d\n", pVfs->iVersion); + raw_printf(p->out, "vfs.szOsFile = %d\n", pVfs->szOsFile); + raw_printf(p->out, "vfs.mxPathname = %d\n", pVfs->mxPathname); + } + } + }else + + if( c=='v' && strncmp(azArg[0], "vfslist", n)==0 ){ + sqlite3_vfs *pVfs; + sqlite3_vfs *pCurrent = 0; + if( p->db ){ + sqlite3_file_control(p->db, "main", SQLITE_FCNTL_VFS_POINTER, &pCurrent); + } + for(pVfs=sqlite3_vfs_find(0); pVfs; pVfs=pVfs->pNext){ + utf8_printf(p->out, "vfs.zName = \"%s\"%s\n", pVfs->zName, + pVfs==pCurrent ? " <--- CURRENT" : ""); + raw_printf(p->out, "vfs.iVersion = %d\n", pVfs->iVersion); + raw_printf(p->out, "vfs.szOsFile = %d\n", pVfs->szOsFile); + raw_printf(p->out, "vfs.mxPathname = %d\n", pVfs->mxPathname); + if( pVfs->pNext ){ + raw_printf(p->out, "-----------------------------------\n"); + } + } + }else + + if( c=='v' && strncmp(azArg[0], "vfsname", n)==0 ){ + const char *zDbName = nArg==2 ? azArg[1] : "main"; + char *zVfsName = 0; + if( p->db ){ + sqlite3_file_control(p->db, zDbName, SQLITE_FCNTL_VFSNAME, &zVfsName); + if( zVfsName ){ + utf8_printf(p->out, "%s\n", zVfsName); + sqlite3_free(zVfsName); + } } - p->bSafeMode = p->bSafeModePersist; - return rc; + }else + + if( c=='w' && strncmp(azArg[0], "wheretrace", n)==0 ){ + unsigned int x = nArg>=2 ? (unsigned int)integerValue(azArg[1]) : 0xffffffff; + sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 3, &x); + }else + + if( c=='w' && strncmp(azArg[0], "width", n)==0 ){ + int j; + assert( nArg<=ArraySize(azArg) ); + p->nWidth = nArg-1; + p->colWidth = realloc(p->colWidth, (p->nWidth+1)*sizeof(int)*2); + if( p->colWidth==0 && p->nWidth>0 ) shell_out_of_memory(); + if( p->nWidth ) p->actualWidth = &p->colWidth[p->nWidth]; + for(j=1; jcolWidth[j-1] = (int)integerValue(azArg[j]); + } + }else + + { + utf8_printf(stderr, "Error: unknown command or invalid arguments: " + " \"%s\". Enter \".help\" for help\n", azArg[0]); + rc = 1; + } + +meta_command_exit: + if( p->outCount ){ + p->outCount--; + if( p->outCount==0 ) output_reset(p); + } + p->bSafeMode = p->bSafeModePersist; + return rc; } /* Line scan result and intermediate states (supporting scan resumption) @@ -21752,9 +21752,9 @@ meta_command_exit: # define CHAR_BIT 8 #endif typedef enum { - QSS_HasDark = 1<flgProgress & SHELL_PROGRESS_RESET ) p->nProgress = 0; - BEGIN_TIMER; - rc = shell_exec(p, zSql, &zErrMsg); - END_TIMER; - if( rc || zErrMsg ){ - char zPrefix[100]; - if( in!=0 || !stdin_is_interactive ){ - sqlite3_snprintf(sizeof(zPrefix), zPrefix, - "Error: near line %d:", startline); - }else{ - sqlite3_snprintf(sizeof(zPrefix), zPrefix, "Error:"); - } - if( zErrMsg!=0 ){ - utf8_printf(stderr, "%s %s\n", zPrefix, zErrMsg); - sqlite3_free(zErrMsg); - zErrMsg = 0; - }else{ - utf8_printf(stderr, "%s %s\n", zPrefix, sqlite3_errmsg(p->db)); - } - return 1; - }else if( ShellHasFlag(p, SHFLG_CountChanges) ){ - char zLineBuf[2000]; - sqlite3_snprintf(sizeof(zLineBuf), zLineBuf, + int rc; + char *zErrMsg = 0; + + open_db(p, 0); + if( ShellHasFlag(p,SHFLG_Backslash) ) resolve_backslashes(zSql); + if( p->flgProgress & SHELL_PROGRESS_RESET ) p->nProgress = 0; + BEGIN_TIMER; + rc = shell_exec(p, zSql, &zErrMsg); + END_TIMER; + if( rc || zErrMsg ){ + char zPrefix[100]; + if( in!=0 || !stdin_is_interactive ){ + sqlite3_snprintf(sizeof(zPrefix), zPrefix, + "Error: near line %d:", startline); + }else{ + sqlite3_snprintf(sizeof(zPrefix), zPrefix, "Error:"); + } + if( zErrMsg!=0 ){ + utf8_printf(stderr, "%s %s\n", zPrefix, zErrMsg); + sqlite3_free(zErrMsg); + zErrMsg = 0; + }else{ + utf8_printf(stderr, "%s %s\n", zPrefix, sqlite3_errmsg(p->db)); + } + return 1; + }else if( ShellHasFlag(p, SHFLG_CountChanges) ){ + char zLineBuf[2000]; + sqlite3_snprintf(sizeof(zLineBuf), zLineBuf, "changes: %lld total_changes: %lld", sqlite3_changes64(p->db), sqlite3_total_changes64(p->db)); - raw_printf(p->out, "%s\n", zLineBuf); - } - return 0; + raw_printf(p->out, "%s\n", zLineBuf); + } + return 0; } @@ -21927,99 +21927,99 @@ static int runOneSqlLine(ShellState *p, char *zSql, FILE *in, int startline){ ** Return the number of errors. */ static int process_input(ShellState *p){ - char *zLine = 0; /* A single input line */ - char *zSql = 0; /* Accumulated SQL text */ - int nLine; /* Length of current line */ - int nSql = 0; /* Bytes of zSql[] used */ - int nAlloc = 0; /* Allocated zSql[] space */ - int rc; /* Error code */ - int errCnt = 0; /* Number of errors seen */ - int startline = 0; /* Line number for start of current input */ - QuickScanState qss = QSS_Start; /* Accumulated line status (so far) */ - - p->lineno = 0; - while( errCnt==0 || !bail_on_error || (p->in==0 && stdin_is_interactive) ){ - fflush(p->out); - zLine = one_input_line(p->in, zLine, nSql>0); - if( zLine==0 ){ - /* End of input */ - if( p->in==0 && stdin_is_interactive ) printf("\n"); - break; - } - if( seenInterrupt ){ - if( p->in!=0 ) break; - seenInterrupt = 0; - } - p->lineno++; - if( QSS_INPLAIN(qss) - && line_is_command_terminator(zLine) - && line_is_complete(zSql, nSql) ){ - memcpy(zLine,";",2); - } - qss = quickscan(zLine, qss); - if( QSS_PLAINWHITE(qss) && nSql==0 ){ - if( ShellHasFlag(p, SHFLG_Echo) ) - printf("%s\n", zLine); - /* Just swallow single-line whitespace */ - qss = QSS_Start; - continue; - } - if( zLine && (zLine[0]=='.' || zLine[0]=='#') && nSql==0 ){ - if( ShellHasFlag(p, SHFLG_Echo) ) printf("%s\n", zLine); - if( zLine[0]=='.' ){ - rc = do_meta_command(zLine, p); - if( rc==2 ){ /* exit requested */ - break; - }else if( rc ){ - errCnt++; - } - } - qss = QSS_Start; - continue; - } - /* No single-line dispositions remain; accumulate line(s). */ - nLine = strlen30(zLine); - if( nSql+nLine+2>=nAlloc ){ - /* Grow buffer by half-again increments when big. */ - nAlloc = nSql+(nSql>>1)+nLine+100; - zSql = realloc(zSql, nAlloc); - if( zSql==0 ) shell_out_of_memory(); - } - if( nSql==0 ){ - int i; - for(i=0; zLine[i] && IsSpace(zLine[i]); i++){} - assert( nAlloc>0 && zSql!=0 ); - memcpy(zSql, zLine+i, nLine+1-i); - startline = p->lineno; - nSql = nLine-i; - }else{ - zSql[nSql++] = '\n'; - memcpy(zSql+nSql, zLine, nLine+1); - nSql += nLine; - } - if( nSql && QSS_SEMITERM(qss) && sqlite3_complete(zSql) ){ - errCnt += runOneSqlLine(p, zSql, p->in, startline); - nSql = 0; - if( p->outCount ){ - output_reset(p); - p->outCount = 0; - }else{ - clearTempFile(p); - } - p->bSafeMode = p->bSafeModePersist; - qss = QSS_Start; - }else if( nSql && QSS_PLAINWHITE(qss) ){ - if( ShellHasFlag(p, SHFLG_Echo) ) printf("%s\n", zSql); - nSql = 0; - qss = QSS_Start; - } - } - if( nSql && QSS_PLAINDARK(qss) ){ - errCnt += runOneSqlLine(p, zSql, p->in, startline); + char *zLine = 0; /* A single input line */ + char *zSql = 0; /* Accumulated SQL text */ + int nLine; /* Length of current line */ + int nSql = 0; /* Bytes of zSql[] used */ + int nAlloc = 0; /* Allocated zSql[] space */ + int rc; /* Error code */ + int errCnt = 0; /* Number of errors seen */ + int startline = 0; /* Line number for start of current input */ + QuickScanState qss = QSS_Start; /* Accumulated line status (so far) */ + + p->lineno = 0; + while( errCnt==0 || !bail_on_error || (p->in==0 && stdin_is_interactive) ){ + fflush(p->out); + zLine = one_input_line(p->in, zLine, nSql>0); + if( zLine==0 ){ + /* End of input */ + if( p->in==0 && stdin_is_interactive ) printf("\n"); + break; } - free(zSql); - free(zLine); - return errCnt>0; + if( seenInterrupt ){ + if( p->in!=0 ) break; + seenInterrupt = 0; + } + p->lineno++; + if( QSS_INPLAIN(qss) + && line_is_command_terminator(zLine) + && line_is_complete(zSql, nSql) ){ + memcpy(zLine,";",2); + } + qss = quickscan(zLine, qss); + if( QSS_PLAINWHITE(qss) && nSql==0 ){ + if( ShellHasFlag(p, SHFLG_Echo) ) + printf("%s\n", zLine); + /* Just swallow single-line whitespace */ + qss = QSS_Start; + continue; + } + if( zLine && (zLine[0]=='.' || zLine[0]=='#') && nSql==0 ){ + if( ShellHasFlag(p, SHFLG_Echo) ) printf("%s\n", zLine); + if( zLine[0]=='.' ){ + rc = do_meta_command(zLine, p); + if( rc==2 ){ /* exit requested */ + break; + }else if( rc ){ + errCnt++; + } + } + qss = QSS_Start; + continue; + } + /* No single-line dispositions remain; accumulate line(s). */ + nLine = strlen30(zLine); + if( nSql+nLine+2>=nAlloc ){ + /* Grow buffer by half-again increments when big. */ + nAlloc = nSql+(nSql>>1)+nLine+100; + zSql = realloc(zSql, nAlloc); + if( zSql==0 ) shell_out_of_memory(); + } + if( nSql==0 ){ + int i; + for(i=0; zLine[i] && IsSpace(zLine[i]); i++){} + assert( nAlloc>0 && zSql!=0 ); + memcpy(zSql, zLine+i, nLine+1-i); + startline = p->lineno; + nSql = nLine-i; + }else{ + zSql[nSql++] = '\n'; + memcpy(zSql+nSql, zLine, nLine+1); + nSql += nLine; + } + if( nSql && QSS_SEMITERM(qss) && sqlite3_complete(zSql) ){ + errCnt += runOneSqlLine(p, zSql, p->in, startline); + nSql = 0; + if( p->outCount ){ + output_reset(p); + p->outCount = 0; + }else{ + clearTempFile(p); + } + p->bSafeMode = p->bSafeModePersist; + qss = QSS_Start; + }else if( nSql && QSS_PLAINWHITE(qss) ){ + if( ShellHasFlag(p, SHFLG_Echo) ) printf("%s\n", zSql); + nSql = 0; + qss = QSS_Start; + } + } + if( nSql && QSS_PLAINDARK(qss) ){ + errCnt += runOneSqlLine(p, zSql, p->in, startline); + } + free(zSql); + free(zLine); + return errCnt>0; } /* @@ -22027,68 +22027,68 @@ static int process_input(ShellState *p){ ** 0 return indicates an error of some kind. */ static char *find_home_dir(int clearFlag){ - static char *home_dir = NULL; - if( clearFlag ){ - free(home_dir); - home_dir = 0; - return 0; - } - if( home_dir ) return home_dir; + static char *home_dir = NULL; + if( clearFlag ){ + free(home_dir); + home_dir = 0; + return 0; + } + if( home_dir ) return home_dir; #if !defined(_WIN32) && !defined(WIN32) && !defined(_WIN32_WCE) \ && !defined(__RTP__) && !defined(_WRS_KERNEL) - { - struct passwd *pwent; - uid_t uid = getuid(); - if( (pwent=getpwuid(uid)) != NULL) { - home_dir = pwent->pw_dir; - } + { + struct passwd *pwent; + uid_t uid = getuid(); + if( (pwent=getpwuid(uid)) != NULL) { + home_dir = pwent->pw_dir; } + } #endif #if defined(_WIN32_WCE) - /* Windows CE (arm-wince-mingw32ce-gcc) does not provide getenv() + /* Windows CE (arm-wince-mingw32ce-gcc) does not provide getenv() */ - home_dir = "/"; + home_dir = "/"; #else #if defined(_WIN32) || defined(WIN32) - if (!home_dir) { - home_dir = getenv("USERPROFILE"); - } + if (!home_dir) { + home_dir = getenv("USERPROFILE"); + } #endif - if (!home_dir) { - home_dir = getenv("HOME"); - } + if (!home_dir) { + home_dir = getenv("HOME"); + } #if defined(_WIN32) || defined(WIN32) - if (!home_dir) { - char *zDrive, *zPath; - int n; - zDrive = getenv("HOMEDRIVE"); - zPath = getenv("HOMEPATH"); - if( zDrive && zPath ){ - n = strlen30(zDrive) + strlen30(zPath) + 1; - home_dir = malloc( n ); - if( home_dir==0 ) return 0; - sqlite3_snprintf(n, home_dir, "%s%s", zDrive, zPath); - return home_dir; - } - home_dir = "c:\\"; - } + if (!home_dir) { + char *zDrive, *zPath; + int n; + zDrive = getenv("HOMEDRIVE"); + zPath = getenv("HOMEPATH"); + if( zDrive && zPath ){ + n = strlen30(zDrive) + strlen30(zPath) + 1; + home_dir = malloc( n ); + if( home_dir==0 ) return 0; + sqlite3_snprintf(n, home_dir, "%s%s", zDrive, zPath); + return home_dir; + } + home_dir = "c:\\"; + } #endif #endif /* !_WIN32_WCE */ - if( home_dir ){ - int n = strlen30(home_dir) + 1; - char *z = malloc( n ); - if( z ) memcpy(z, home_dir, n); - home_dir = z; - } + if( home_dir ){ + int n = strlen30(home_dir) + 1; + char *z = malloc( n ); + if( z ) memcpy(z, home_dir, n); + home_dir = z; + } - return home_dir; + return home_dir; } /* @@ -22098,39 +22098,39 @@ static char *find_home_dir(int clearFlag){ ** Returns the number of errors. */ static void process_sqliterc( - ShellState *p, /* Configuration data */ - const char *sqliterc_override /* Name of config file. NULL to use default */ + ShellState *p, /* Configuration data */ + const char *sqliterc_override /* Name of config file. NULL to use default */ ){ - char *home_dir = NULL; - const char *sqliterc = sqliterc_override; - char *zBuf = 0; - FILE *inSaved = p->in; - int savedLineno = p->lineno; - - if (sqliterc == NULL) { - home_dir = find_home_dir(0); - if( home_dir==0 ){ - raw_printf(stderr, "-- warning: cannot find home directory;" - " cannot read ~/.sqliterc\n"); - return; - } - zBuf = sqlite3_mprintf("%s/.sqliterc",home_dir); - sqliterc = zBuf; - } - p->in = fopen(sqliterc,"rb"); - if( p->in ){ - if( stdin_is_interactive ){ - utf8_printf(stderr,"-- Loading resources from %s\n",sqliterc); - } - if( process_input(p) && bail_on_error ) exit(1); - fclose(p->in); - }else if( sqliterc_override!=0 ){ - utf8_printf(stderr,"cannot open: \"%s\"\n", sqliterc); - if( bail_on_error ) exit(1); - } - p->in = inSaved; - p->lineno = savedLineno; - sqlite3_free(zBuf); + char *home_dir = NULL; + const char *sqliterc = sqliterc_override; + char *zBuf = 0; + FILE *inSaved = p->in; + int savedLineno = p->lineno; + + if (sqliterc == NULL) { + home_dir = find_home_dir(0); + if( home_dir==0 ){ + raw_printf(stderr, "-- warning: cannot find home directory;" + " cannot read ~/.sqliterc\n"); + return; + } + zBuf = sqlite3_mprintf("%s/.sqliterc",home_dir); + sqliterc = zBuf; + } + p->in = fopen(sqliterc,"rb"); + if( p->in ){ + if( stdin_is_interactive ){ + utf8_printf(stderr,"-- Loading resources from %s\n",sqliterc); + } + if( process_input(p) && bail_on_error ) exit(1); + fclose(p->in); + }else if( sqliterc_override!=0 ){ + utf8_printf(stderr,"cannot open: \"%s\"\n", sqliterc); + if( bail_on_error ) exit(1); + } + p->in = inSaved; + p->lineno = savedLineno; + sqlite3_free(zBuf); } /* @@ -22138,76 +22138,76 @@ static void process_sqliterc( */ static const char zOptions[] = #if defined(SQLITE_HAVE_ZLIB) && !defined(SQLITE_OMIT_VIRTUALTABLE) - " -A ARGS... run \".archive ARGS\" and exit\n" + " -A ARGS... run \".archive ARGS\" and exit\n" #endif - " -append append the database to the end of the file\n" - " -ascii set output mode to 'ascii'\n" - " -bail stop after hitting an error\n" - " -batch force batch I/O\n" - " -box set output mode to 'box'\n" - " -column set output mode to 'column'\n" - " -cmd COMMAND run \"COMMAND\" before reading stdin\n" - " -csv set output mode to 'csv'\n" + " -append append the database to the end of the file\n" + " -ascii set output mode to 'ascii'\n" + " -bail stop after hitting an error\n" + " -batch force batch I/O\n" + " -box set output mode to 'box'\n" + " -column set output mode to 'column'\n" + " -cmd COMMAND run \"COMMAND\" before reading stdin\n" + " -csv set output mode to 'csv'\n" #if !defined(SQLITE_OMIT_DESERIALIZE) - " -deserialize open the database using sqlite3_deserialize()\n" + " -deserialize open the database using sqlite3_deserialize()\n" #endif - " -echo print commands before execution\n" - " -init FILENAME read/process named file\n" - " -[no]header turn headers on or off\n" + " -echo print commands before execution\n" + " -init FILENAME read/process named file\n" + " -[no]header turn headers on or off\n" #if defined(SQLITE_ENABLE_MEMSYS3) || defined(SQLITE_ENABLE_MEMSYS5) - " -heap SIZE Size of heap for memsys3 or memsys5\n" + " -heap SIZE Size of heap for memsys3 or memsys5\n" #endif - " -help show this message\n" - " -html set output mode to HTML\n" - " -interactive force interactive I/O\n" - " -json set output mode to 'json'\n" - " -line set output mode to 'line'\n" - " -list set output mode to 'list'\n" - " -lookaside SIZE N use N entries of SZ bytes for lookaside memory\n" - " -markdown set output mode to 'markdown'\n" + " -help show this message\n" + " -html set output mode to HTML\n" + " -interactive force interactive I/O\n" + " -json set output mode to 'json'\n" + " -line set output mode to 'line'\n" + " -list set output mode to 'list'\n" + " -lookaside SIZE N use N entries of SZ bytes for lookaside memory\n" + " -markdown set output mode to 'markdown'\n" #if !defined(SQLITE_OMIT_DESERIALIZE) - " -maxsize N maximum size for a --deserialize database\n" + " -maxsize N maximum size for a --deserialize database\n" #endif - " -memtrace trace all memory allocations and deallocations\n" - " -mmap N default mmap size set to N\n" + " -memtrace trace all memory allocations and deallocations\n" + " -mmap N default mmap size set to N\n" #ifdef SQLITE_ENABLE_MULTIPLEX - " -multiplex enable the multiplexor VFS\n" + " -multiplex enable the multiplexor VFS\n" #endif - " -newline SEP set output row separator. Default: '\\n'\n" - " -nofollow refuse to open symbolic links to database files\n" - " -nonce STRING set the safe-mode escape nonce\n" - " -nullvalue TEXT set text string for NULL values. Default ''\n" - " -pagecache SIZE N use N slots of SZ bytes each for page cache memory\n" - " -quote set output mode to 'quote'\n" - " -readonly open the database read-only\n" - " -safe enable safe-mode\n" - " -separator SEP set output column separator. Default: '|'\n" + " -newline SEP set output row separator. Default: '\\n'\n" + " -nofollow refuse to open symbolic links to database files\n" + " -nonce STRING set the safe-mode escape nonce\n" + " -nullvalue TEXT set text string for NULL values. Default ''\n" + " -pagecache SIZE N use N slots of SZ bytes each for page cache memory\n" + " -quote set output mode to 'quote'\n" + " -readonly open the database read-only\n" + " -safe enable safe-mode\n" + " -separator SEP set output column separator. Default: '|'\n" #ifdef SQLITE_ENABLE_SORTER_REFERENCES - " -sorterref SIZE sorter references threshold size\n" + " -sorterref SIZE sorter references threshold size\n" #endif - " -stats print memory stats before each finalize\n" - " -table set output mode to 'table'\n" - " -tabs set output mode to 'tabs'\n" - " -version show SQLite version\n" - " -vfs NAME use NAME as the default VFS\n" + " -stats print memory stats before each finalize\n" + " -table set output mode to 'table'\n" + " -tabs set output mode to 'tabs'\n" + " -version show SQLite version\n" + " -vfs NAME use NAME as the default VFS\n" #ifdef SQLITE_ENABLE_VFSTRACE - " -vfstrace enable tracing of all VFS calls\n" + " -vfstrace enable tracing of all VFS calls\n" #endif #ifdef SQLITE_HAVE_ZLIB - " -zip open the file as a ZIP Archive\n" + " -zip open the file as a ZIP Archive\n" #endif - ; +; static void usage(int showDetail){ - utf8_printf(stderr, - "Usage: %s [OPTIONS] FILENAME [SQL]\n" - "FILENAME is the name of an SQLite database. A new database is created\n" - "if the file does not previously exist.\n", Argv0); - if( showDetail ){ - utf8_printf(stderr, "OPTIONS include:\n%s", zOptions); - }else{ - raw_printf(stderr, "Use the -help option for additional information\n"); - } - exit(1); + utf8_printf(stderr, + "Usage: %s [OPTIONS] FILENAME [SQL]\n" + "FILENAME is the name of an SQLite database. A new database is created\n" + "if the file does not previously exist.\n", Argv0); + if( showDetail ){ + utf8_printf(stderr, "OPTIONS include:\n%s", zOptions); + }else{ + raw_printf(stderr, "Use the -help option for additional information\n"); + } + exit(1); } /* @@ -22215,30 +22215,30 @@ static void usage(int showDetail){ ** error message if it is initialized. */ static void verify_uninitialized(void){ - if( sqlite3_config(-1)==SQLITE_MISUSE ){ - utf8_printf(stdout, "WARNING: attempt to configure SQLite after" - " initialization.\n"); - } + if( sqlite3_config(-1)==SQLITE_MISUSE ){ + utf8_printf(stdout, "WARNING: attempt to configure SQLite after" + " initialization.\n"); + } } /* ** Initialize the state information in data */ static void main_init(ShellState *data) { - memset(data, 0, sizeof(*data)); - data->normalMode = data->cMode = data->mode = MODE_List; - data->autoExplain = 1; - data->pAuxDb = &data->aAuxDb[0]; - memcpy(data->colSeparator,SEP_Column, 2); - memcpy(data->rowSeparator,SEP_Row, 2); - data->showHeader = 0; - data->shellFlgs = SHFLG_Lookaside; - verify_uninitialized(); - sqlite3_config(SQLITE_CONFIG_URI, 1); - sqlite3_config(SQLITE_CONFIG_LOG, shellLog, data); - sqlite3_config(SQLITE_CONFIG_MULTITHREAD); - sqlite3_snprintf(sizeof(mainPrompt), mainPrompt,"sqlite> "); - sqlite3_snprintf(sizeof(continuePrompt), continuePrompt," ...> "); + memset(data, 0, sizeof(*data)); + data->normalMode = data->cMode = data->mode = MODE_List; + data->autoExplain = 1; + data->pAuxDb = &data->aAuxDb[0]; + memcpy(data->colSeparator,SEP_Column, 2); + memcpy(data->rowSeparator,SEP_Row, 2); + data->showHeader = 0; + data->shellFlgs = SHFLG_Lookaside; + verify_uninitialized(); + sqlite3_config(SQLITE_CONFIG_URI, 1); + sqlite3_config(SQLITE_CONFIG_LOG, shellLog, data); + sqlite3_config(SQLITE_CONFIG_MULTITHREAD); + sqlite3_snprintf(sizeof(mainPrompt), mainPrompt,"sqlite> "); + sqlite3_snprintf(sizeof(continuePrompt), continuePrompt," ...> "); } /* @@ -22247,21 +22247,21 @@ static void main_init(ShellState *data) { #ifdef _WIN32 static void printBold(const char *zText){ #if !SQLITE_OS_WINRT - HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE); - CONSOLE_SCREEN_BUFFER_INFO defaultScreenInfo; - GetConsoleScreenBufferInfo(out, &defaultScreenInfo); - SetConsoleTextAttribute(out, - FOREGROUND_RED|FOREGROUND_INTENSITY - ); + HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE); + CONSOLE_SCREEN_BUFFER_INFO defaultScreenInfo; + GetConsoleScreenBufferInfo(out, &defaultScreenInfo); + SetConsoleTextAttribute(out, + FOREGROUND_RED|FOREGROUND_INTENSITY + ); #endif - printf("%s", zText); + printf("%s", zText); #if !SQLITE_OS_WINRT - SetConsoleTextAttribute(out, defaultScreenInfo.wAttributes); + SetConsoleTextAttribute(out, defaultScreenInfo.wAttributes); #endif } #else static void printBold(const char *zText){ - printf("\033[1m%s\033[0m", zText); + printf("\033[1m%s\033[0m", zText); } #endif @@ -22270,12 +22270,12 @@ static void printBold(const char *zText){ ** is available. */ static char *cmdline_option_value(int argc, char **argv, int i){ - if( i==argc ){ - utf8_printf(stderr, "%s: Error: missing argument to %s\n", + if( i==argc ){ + utf8_printf(stderr, "%s: Error: missing argument to %s\n", argv[0], argv[argc-1]); - exit(1); - } - return argv[i]; + exit(1); + } + return argv[i]; } #ifndef SQLITE_SHELL_IS_UTF8 @@ -22291,577 +22291,577 @@ static char *cmdline_option_value(int argc, char **argv, int i){ int SQLITE_CDECL main(int argc, char **argv){ #else int SQLITE_CDECL wmain(int argc, wchar_t **wargv){ - char **argv; + char **argv; #endif - char *zErrMsg = 0; - ShellState data; - const char *zInitFile = 0; - int i; - int rc = 0; - int warnInmemoryDb = 0; - int readStdin = 1; - int nCmd = 0; - char **azCmd = 0; - const char *zVfs = 0; /* Value of -vfs command-line option */ + char *zErrMsg = 0; + ShellState data; + const char *zInitFile = 0; + int i; + int rc = 0; + int warnInmemoryDb = 0; + int readStdin = 1; + int nCmd = 0; + char **azCmd = 0; + const char *zVfs = 0; /* Value of -vfs command-line option */ #if !SQLITE_SHELL_IS_UTF8 - char **argvToFree = 0; - int argcToFree = 0; + char **argvToFree = 0; + int argcToFree = 0; #endif - setBinaryMode(stdin, 0); - setvbuf(stderr, 0, _IONBF, 0); /* Make sure stderr is unbuffered */ - stdin_is_interactive = isatty(0); - stdout_is_console = isatty(1); + setBinaryMode(stdin, 0); + setvbuf(stderr, 0, _IONBF, 0); /* Make sure stderr is unbuffered */ + stdin_is_interactive = isatty(0); + stdout_is_console = isatty(1); #ifdef SQLITE_DEBUG - registerOomSimulator(); + registerOomSimulator(); #endif #if !defined(_WIN32_WCE) - if( getenv("SQLITE_DEBUG_BREAK") ){ - if( isatty(0) && isatty(2) ){ - fprintf(stderr, - "attach debugger to process %d and press any key to continue.\n", - GETPID()); - fgetc(stdin); - }else{ + if( getenv("SQLITE_DEBUG_BREAK") ){ + if( isatty(0) && isatty(2) ){ + fprintf(stderr, + "attach debugger to process %d and press any key to continue.\n", + GETPID()); + fgetc(stdin); + }else{ #if defined(_WIN32) || defined(WIN32) #if SQLITE_OS_WINRT - __debugbreak(); + __debugbreak(); #else - DebugBreak(); + DebugBreak(); #endif #elif defined(SIGTRAP) - raise(SIGTRAP); + raise(SIGTRAP); #endif - } } + } #endif #if USE_SYSTEM_SQLITE+0!=1 - if( strncmp(sqlite3_sourceid(),SQLITE_SOURCE_ID,60)!=0 ){ - utf8_printf(stderr, "SQLite header and source version mismatch\n%s\n%s\n", + if( strncmp(sqlite3_sourceid(),SQLITE_SOURCE_ID,60)!=0 ){ + utf8_printf(stderr, "SQLite header and source version mismatch\n%s\n%s\n", sqlite3_sourceid(), SQLITE_SOURCE_ID); - exit(1); - } + exit(1); + } #endif - main_init(&data); + main_init(&data); - /* On Windows, we must translate command-line arguments into UTF-8. + /* On Windows, we must translate command-line arguments into UTF-8. ** The SQLite memory allocator subsystem has to be enabled in order to ** do this. But we want to run an sqlite3_shutdown() afterwards so that ** subsequent sqlite3_config() calls will work. So copy all results into ** memory that does not come from the SQLite memory allocator. */ #if !SQLITE_SHELL_IS_UTF8 - sqlite3_initialize(); - argvToFree = malloc(sizeof(argv[0])*argc*2); - argcToFree = argc; - argv = argvToFree + argc; - if( argv==0 ) shell_out_of_memory(); - for(i=0; i=1 && argv && argv[0] ); - Argv0 = argv[0]; + assert( argc>=1 && argv && argv[0] ); + Argv0 = argv[0]; - /* Make sure we have a valid signal handler early, before anything + /* Make sure we have a valid signal handler early, before anything ** else is done. */ #ifdef SIGINT - signal(SIGINT, interrupt_handler); + signal(SIGINT, interrupt_handler); #elif (defined(_WIN32) || defined(WIN32)) && !defined(_WIN32_WCE) - SetConsoleCtrlHandler(ConsoleCtrlHandler, TRUE); + SetConsoleCtrlHandler(ConsoleCtrlHandler, TRUE); #endif #ifdef SQLITE_SHELL_DBNAME_PROC - { - /* If the SQLITE_SHELL_DBNAME_PROC macro is defined, then it is the name + { + /* If the SQLITE_SHELL_DBNAME_PROC macro is defined, then it is the name ** of a C-function that will provide the name of the database file. Use ** this compile-time option to embed this shell program in larger ** applications. */ - extern void SQLITE_SHELL_DBNAME_PROC(const char**); - SQLITE_SHELL_DBNAME_PROC(&data.pAuxDb->zDbFilename); - warnInmemoryDb = 0; - } + extern void SQLITE_SHELL_DBNAME_PROC(const char**); + SQLITE_SHELL_DBNAME_PROC(&data.pAuxDb->zDbFilename); + warnInmemoryDb = 0; + } #endif - /* Do an initial pass through the command-line argument to locate + /* Do an initial pass through the command-line argument to locate ** the name of the database file, the name of the initialization file, ** the size of the alternative malloc heap, ** and the first command to execute. */ - verify_uninitialized(); - for(i=1; izDbFilename==0 ){ - data.aAuxDb->zDbFilename = z; - }else{ - /* Excesss arguments are interpreted as SQL (or dot-commands) and + verify_uninitialized(); + for(i=1; izDbFilename==0 ){ + data.aAuxDb->zDbFilename = z; + }else{ + /* Excesss arguments are interpreted as SQL (or dot-commands) and ** mean that nothing is read from stdin */ - readStdin = 0; - nCmd++; - azCmd = realloc(azCmd, sizeof(azCmd[0])*nCmd); - if( azCmd==0 ) shell_out_of_memory(); - azCmd[nCmd-1] = z; - } - } - if( z[1]=='-' ) z++; - if( strcmp(z,"-separator")==0 - || strcmp(z,"-nullvalue")==0 - || strcmp(z,"-newline")==0 - || strcmp(z,"-cmd")==0 - ){ - (void)cmdline_option_value(argc, argv, ++i); - }else if( strcmp(z,"-init")==0 ){ - zInitFile = cmdline_option_value(argc, argv, ++i); - }else if( strcmp(z,"-batch")==0 ){ - /* Need to check for batch mode here to so we can avoid printing + readStdin = 0; + nCmd++; + azCmd = realloc(azCmd, sizeof(azCmd[0])*nCmd); + if( azCmd==0 ) shell_out_of_memory(); + azCmd[nCmd-1] = z; + } + } + if( z[1]=='-' ) z++; + if( strcmp(z,"-separator")==0 + || strcmp(z,"-nullvalue")==0 + || strcmp(z,"-newline")==0 + || strcmp(z,"-cmd")==0 + ){ + (void)cmdline_option_value(argc, argv, ++i); + }else if( strcmp(z,"-init")==0 ){ + zInitFile = cmdline_option_value(argc, argv, ++i); + }else if( strcmp(z,"-batch")==0 ){ + /* Need to check for batch mode here to so we can avoid printing ** informational messages (like from process_sqliterc) before ** we do the actual processing of arguments later in a second pass. */ - stdin_is_interactive = 0; - }else if( strcmp(z,"-heap")==0 ){ + stdin_is_interactive = 0; + }else if( strcmp(z,"-heap")==0 ){ #if defined(SQLITE_ENABLE_MEMSYS3) || defined(SQLITE_ENABLE_MEMSYS5) - const char *zSize; - sqlite3_int64 szHeap; + const char *zSize; + sqlite3_int64 szHeap; - zSize = cmdline_option_value(argc, argv, ++i); - szHeap = integerValue(zSize); - if( szHeap>0x7fff0000 ) szHeap = 0x7fff0000; - sqlite3_config(SQLITE_CONFIG_HEAP, malloc((int)szHeap), (int)szHeap, 64); + zSize = cmdline_option_value(argc, argv, ++i); + szHeap = integerValue(zSize); + if( szHeap>0x7fff0000 ) szHeap = 0x7fff0000; + sqlite3_config(SQLITE_CONFIG_HEAP, malloc((int)szHeap), (int)szHeap, 64); #else - (void)cmdline_option_value(argc, argv, ++i); + (void)cmdline_option_value(argc, argv, ++i); #endif - }else if( strcmp(z,"-pagecache")==0 ){ - sqlite3_int64 n, sz; - sz = integerValue(cmdline_option_value(argc,argv,++i)); - if( sz>70000 ) sz = 70000; - if( sz<0 ) sz = 0; - n = integerValue(cmdline_option_value(argc,argv,++i)); - if( sz>0 && n>0 && 0xffffffffffffLL/sz0 && sz>0) ? malloc(n*sz) : 0, sz, n); - data.shellFlgs |= SHFLG_Pagecache; - }else if( strcmp(z,"-lookaside")==0 ){ - int n, sz; - sz = (int)integerValue(cmdline_option_value(argc,argv,++i)); - if( sz<0 ) sz = 0; - n = (int)integerValue(cmdline_option_value(argc,argv,++i)); - if( n<0 ) n = 0; - sqlite3_config(SQLITE_CONFIG_LOOKASIDE, sz, n); - if( sz*n==0 ) data.shellFlgs &= ~SHFLG_Lookaside; - }else if( strcmp(z,"-threadsafe")==0 ){ - int n; - n = (int)integerValue(cmdline_option_value(argc,argv,++i)); - switch( n ){ - case 0: sqlite3_config(SQLITE_CONFIG_SINGLETHREAD); break; - case 2: sqlite3_config(SQLITE_CONFIG_MULTITHREAD); break; - default: sqlite3_config(SQLITE_CONFIG_SERIALIZED); break; - } + }else if( strcmp(z,"-pagecache")==0 ){ + sqlite3_int64 n, sz; + sz = integerValue(cmdline_option_value(argc,argv,++i)); + if( sz>70000 ) sz = 70000; + if( sz<0 ) sz = 0; + n = integerValue(cmdline_option_value(argc,argv,++i)); + if( sz>0 && n>0 && 0xffffffffffffLL/sz0 && sz>0) ? malloc(n*sz) : 0, sz, n); + data.shellFlgs |= SHFLG_Pagecache; + }else if( strcmp(z,"-lookaside")==0 ){ + int n, sz; + sz = (int)integerValue(cmdline_option_value(argc,argv,++i)); + if( sz<0 ) sz = 0; + n = (int)integerValue(cmdline_option_value(argc,argv,++i)); + if( n<0 ) n = 0; + sqlite3_config(SQLITE_CONFIG_LOOKASIDE, sz, n); + if( sz*n==0 ) data.shellFlgs &= ~SHFLG_Lookaside; + }else if( strcmp(z,"-threadsafe")==0 ){ + int n; + n = (int)integerValue(cmdline_option_value(argc,argv,++i)); + switch( n ){ + case 0: sqlite3_config(SQLITE_CONFIG_SINGLETHREAD); break; + case 2: sqlite3_config(SQLITE_CONFIG_MULTITHREAD); break; + default: sqlite3_config(SQLITE_CONFIG_SERIALIZED); break; + } #ifdef SQLITE_ENABLE_VFSTRACE - }else if( strcmp(z,"-vfstrace")==0 ){ - extern int vfstrace_register( - const char *zTraceName, - const char *zOldVfsName, - int (*xOut)(const char*,void*), - void *pOutArg, - int makeDefault - ); - vfstrace_register("trace",0,(int(*)(const char*,void*))fputs,stderr,1); + }else if( strcmp(z,"-vfstrace")==0 ){ + extern int vfstrace_register( + const char *zTraceName, + const char *zOldVfsName, + int (*xOut)(const char*,void*), + void *pOutArg, + int makeDefault + ); + vfstrace_register("trace",0,(int(*)(const char*,void*))fputs,stderr,1); #endif #ifdef SQLITE_ENABLE_MULTIPLEX - }else if( strcmp(z,"-multiplex")==0 ){ - extern int sqlite3_multiple_initialize(const char*,int); - sqlite3_multiplex_initialize(0, 1); + }else if( strcmp(z,"-multiplex")==0 ){ + extern int sqlite3_multiple_initialize(const char*,int); + sqlite3_multiplex_initialize(0, 1); #endif - }else if( strcmp(z,"-mmap")==0 ){ - sqlite3_int64 sz = integerValue(cmdline_option_value(argc,argv,++i)); - sqlite3_config(SQLITE_CONFIG_MMAP_SIZE, sz, sz); + }else if( strcmp(z,"-mmap")==0 ){ + sqlite3_int64 sz = integerValue(cmdline_option_value(argc,argv,++i)); + sqlite3_config(SQLITE_CONFIG_MMAP_SIZE, sz, sz); #ifdef SQLITE_ENABLE_SORTER_REFERENCES - }else if( strcmp(z,"-sorterref")==0 ){ - sqlite3_int64 sz = integerValue(cmdline_option_value(argc,argv,++i)); - sqlite3_config(SQLITE_CONFIG_SORTERREF_SIZE, (int)sz); + }else if( strcmp(z,"-sorterref")==0 ){ + sqlite3_int64 sz = integerValue(cmdline_option_value(argc,argv,++i)); + sqlite3_config(SQLITE_CONFIG_SORTERREF_SIZE, (int)sz); #endif - }else if( strcmp(z,"-vfs")==0 ){ - zVfs = cmdline_option_value(argc, argv, ++i); + }else if( strcmp(z,"-vfs")==0 ){ + zVfs = cmdline_option_value(argc, argv, ++i); #ifdef SQLITE_HAVE_ZLIB - }else if( strcmp(z,"-zip")==0 ){ - data.openMode = SHELL_OPEN_ZIPFILE; + }else if( strcmp(z,"-zip")==0 ){ + data.openMode = SHELL_OPEN_ZIPFILE; #endif - }else if( strcmp(z,"-append")==0 ){ - data.openMode = SHELL_OPEN_APPENDVFS; + }else if( strcmp(z,"-append")==0 ){ + data.openMode = SHELL_OPEN_APPENDVFS; #ifndef SQLITE_OMIT_DESERIALIZE - }else if( strcmp(z,"-deserialize")==0 ){ - data.openMode = SHELL_OPEN_DESERIALIZE; - }else if( strcmp(z,"-maxsize")==0 && i+1zDbFilename==0 ){ + if( data.pAuxDb->zDbFilename==0 ){ #ifndef SQLITE_OMIT_MEMORYDB - data.pAuxDb->zDbFilename = ":memory:"; - warnInmemoryDb = argc==1; + data.pAuxDb->zDbFilename = ":memory:"; + warnInmemoryDb = argc==1; #else - utf8_printf(stderr,"%s: Error: no database filename specified\n", Argv0); - return 1; + utf8_printf(stderr,"%s: Error: no database filename specified\n", Argv0); + return 1; #endif - } - data.out = stdout; - sqlite3_appendvfs_init(0,0,0); + } + data.out = stdout; + sqlite3_appendvfs_init(0,0,0); - /* Go ahead and open the database file if it already exists. If the + /* Go ahead and open the database file if it already exists. If the ** file does not exist, delay opening it. This prevents empty database ** files from being created if a user mistypes the database name argument ** to the sqlite command-line tool. */ - if( access(data.pAuxDb->zDbFilename, 0)==0 ){ - open_db(&data, 0); - } + if( access(data.pAuxDb->zDbFilename, 0)==0 ){ + open_db(&data, 0); + } - /* Process the initialization file if there is one. If no -init option + /* Process the initialization file if there is one. If no -init option ** is given on the command line, look for a file named ~/.sqliterc and ** try to process it. */ - process_sqliterc(&data,zInitFile); + process_sqliterc(&data,zInitFile); - /* Make a second pass through the command-line argument and set + /* Make a second pass through the command-line argument and set ** options. This second pass is delayed until after the initialization ** file is processed so that the command-line arguments will override ** settings in the initialization file. */ - for(i=1; i0 ){ - utf8_printf(stderr, "Error: cannot mix regular SQL or dot-commands" - " with \"%s\"\n", z); - return 1; - } - open_db(&data, OPEN_DB_ZIPFILE); - if( z[2] ){ - argv[i] = &z[2]; - arDotCommand(&data, 1, argv+(i-1), argc-(i-1)); - }else{ - arDotCommand(&data, 1, argv+i, argc-i); - } - readStdin = 0; - break; + }else if( strncmp(z, "-A", 2)==0 ){ + if( nCmd>0 ){ + utf8_printf(stderr, "Error: cannot mix regular SQL or dot-commands" + " with \"%s\"\n", z); + return 1; + } + open_db(&data, OPEN_DB_ZIPFILE); + if( z[2] ){ + argv[i] = &z[2]; + arDotCommand(&data, 1, argv+(i-1), argc-(i-1)); + }else{ + arDotCommand(&data, 1, argv+i, argc-i); + } + readStdin = 0; + break; #endif - }else if( strcmp(z,"-safe")==0 ){ - data.bSafeMode = data.bSafeModePersist = 1; - }else{ - utf8_printf(stderr,"%s: Error: unknown option: %s\n", Argv0, z); - raw_printf(stderr,"Use -help for a list of options.\n"); - return 1; - } - data.cMode = data.mode; + }else if( strcmp(z,"-safe")==0 ){ + data.bSafeMode = data.bSafeModePersist = 1; + }else{ + utf8_printf(stderr,"%s: Error: unknown option: %s\n", Argv0, z); + raw_printf(stderr,"Use -help for a list of options.\n"); + return 1; } + data.cMode = data.mode; + } - if( !readStdin ){ - /* Run all arguments that do not begin with '-' as if they were separate + if( !readStdin ){ + /* Run all arguments that do not begin with '-' as if they were separate ** command-line inputs, except for the argToSkip argument which contains ** the database filename. */ - for(i=0; iflags; - int mDbFlagsBackup = db->mDbFlags; + u64 flagsBackup = db->flags; + u32 mDbFlagsBackup = db->mDbFlags; int nChangeBackup = db->nChange; int nTotalChangeBackup = db->nTotalChange; int (*xTraceBackup)(u32,void*,void*,void*) = db->trace.xV2; @@ -239678,4 +239678,4 @@ static const sqlite3_api_routines_hw sqlite3HwApis = { EXPORT_SYMBOLS const sqlite3_api_routines *sqlite3_export_symbols = &sqlite3Apis; EXPORT_SYMBOLS const sqlite3_api_routines_hw *sqlite3_export_hw_symbols = &sqlite3HwApis; -#endif +#endif \ No newline at end of file diff --git a/mock/src/mock_device_manager.cpp b/mock/src/mock_device_manager.cpp index 7e153983..4296e63a 100644 --- a/mock/src/mock_device_manager.cpp +++ b/mock/src/mock_device_manager.cpp @@ -22,13 +22,6 @@ DeviceManager &DeviceManager::GetInstance() return DeviceManagerImpl::GetInstance(); } -int DeviceManagerImpl::GetEncryptedUuidByNetworkId(const std::string &pkgName, const std::string &networkId, - std::string &uuid) -{ - uuid = networkId; - return 0; -} - DeviceManagerImpl &DeviceManagerImpl::GetInstance() { static DeviceManagerImpl instance; @@ -97,23 +90,11 @@ int32_t DeviceManagerImpl::VerifyAuthentication(const std::string &pkgName, cons { return 0; } -int32_t DeviceManagerImpl::RegisterDeviceManagerFaCallback(const std::string &packageName, - std::shared_ptr callback) -{ - return 0; -} -int32_t DeviceManagerImpl::UnRegisterDeviceManagerFaCallback(const std::string &pkgName) -{ - return 0; -} + int32_t DeviceManagerImpl::GetFaParam(const std::string &pkgName, DmAuthParam &faParam) { return 0; } -int32_t DeviceManagerImpl::SetUserOperation(const std::string &pkgName, int32_t action) -{ - return 0; -} int32_t DeviceManagerImpl::GetUdidByNetworkId(const std::string &pkgName, const std::string &netWorkId, std::string &udid) { @@ -177,10 +158,32 @@ int32_t DeviceManagerImpl::NotifyEvent(const std::string &pkgName, const int32_t { return 0; } +int32_t DeviceManagerImpl::GetDeviceInfo(const std::string &pkgName, const std::string networkId, + DmDeviceInfo &deviceInfo) +{ + return 0; +} +int32_t DeviceManagerImpl::SetUserOperation(const std::string &pkgName, int32_t action, const std::string ¶ms) +{ + return 0; +} -int DeviceManagerImpl::GenerateEncryptedUuid(const std::string &pkgName, const std::string &uuid, - const std::string &appId, std::string &encryptedUuid) +int32_t DeviceManagerImpl::GetEncryptedUuidByNetworkId(const std::string &pkgName, const std::string &networkId, std::string &uuid) { + if (pkgName.empty() || networkId.empty() || networkId == std::string("no_exist_device_id") || + networkId.find("invalid_device") != std::string::npos || networkId == std::string("1234567890")) { + return -1; + } + uuid = networkId; + return 0; +} + +int32_t DeviceManagerImpl::GenerateEncryptedUuid(const std::string &pkgName, const std::string &uuid, const std::string &appId, + std::string &encryptedUuid) +{ + if (pkgName.empty() || uuid.empty()) { + return -1; + } encryptedUuid = uuid; return 0; } diff --git a/mock/src/mock_huks.cpp b/mock/src/mock_huks.cpp index 7b3abc8d..3d1fb235 100644 --- a/mock/src/mock_huks.cpp +++ b/mock/src/mock_huks.cpp @@ -13,24 +13,489 @@ * limitations under the License. */ #include +#include +#include #include #include #include +#include +#include +#include #include "securec.h" -int32_t HksInitParamSet(struct HksParamSet **paramSet) { return HKS_SUCCESS; } -int32_t HksAddParams(struct HksParamSet *paramSet, const struct HksParam *params, uint32_t paramCnt) +static std::set KEYS; + +void *HksMalloc(size_t size) +{ + return malloc(size); +} + +int32_t HksMemCmp(const void *ptr1, const void *ptr2, uint32_t size) +{ + return memcmp(ptr1, ptr2, size); +} +static uint32_t g_validTags[] = { + HKS_TAG_ALGORITHM, + HKS_TAG_PURPOSE, + HKS_TAG_KEY_SIZE, + HKS_TAG_DIGEST, + HKS_TAG_PADDING, + HKS_TAG_BLOCK_MODE, + HKS_TAG_KEY_TYPE, + HKS_TAG_ASSOCIATED_DATA, + HKS_TAG_NONCE, + HKS_TAG_IV, + + HKS_TAG_SALT, + HKS_TAG_PWD, + HKS_TAG_INFO, + HKS_TAG_ITERATION, + + HKS_TAG_KEY_GENERATE_TYPE, + HKS_TAG_DERIVE_MAIN_KEY, + HKS_TAG_DERIVE_FACTOR, + HKS_TAG_DERIVE_ALG, + HKS_TAG_AGREE_ALG, + HKS_TAG_AGREE_PUBLIC_KEY_IS_KEY_ALIAS, + HKS_TAG_AGREE_PRIVATE_KEY_ALIAS, + HKS_TAG_AGREE_PUBLIC_KEY, + HKS_TAG_KEY_ALIAS, + HKS_TAG_DERIVE_KEY_SIZE, + HKS_TAG_IMPORT_KEY_TYPE, + HKS_TAG_UNWRAP_ALGORITHM_SUITE, + HKS_TAG_DERIVE_AGREE_KEY_STORAGE_FLAG, + HKS_TAG_RSA_PSS_SALT_LEN_TYPE, + + HKS_TAG_ACTIVE_DATETIME, + HKS_TAG_ORIGINATION_EXPIRE_DATETIME, + HKS_TAG_USAGE_EXPIRE_DATETIME, + HKS_TAG_CREATION_DATETIME, + + HKS_TAG_ALL_USERS, + HKS_TAG_USER_ID, + HKS_TAG_NO_AUTH_REQUIRED, + HKS_TAG_USER_AUTH_TYPE, + HKS_TAG_AUTH_TIMEOUT, + HKS_TAG_AUTH_TOKEN, + + HKS_TAG_OS_VERSION, + HKS_TAG_OS_PATCHLEVEL, + + HKS_TAG_ATTESTATION_CHALLENGE, + HKS_TAG_ATTESTATION_APPLICATION_ID, + HKS_TAG_ATTESTATION_ID_BRAND, + HKS_TAG_ATTESTATION_ID_DEVICE, + HKS_TAG_ATTESTATION_ID_PRODUCT, + HKS_TAG_ATTESTATION_ID_SERIAL, + HKS_TAG_ATTESTATION_ID_IMEI, + HKS_TAG_ATTESTATION_ID_MEID, + HKS_TAG_ATTESTATION_ID_MANUFACTURER, + HKS_TAG_ATTESTATION_ID_MODEL, + HKS_TAG_ATTESTATION_ID_ALIAS, + HKS_TAG_ATTESTATION_ID_SOCID, + HKS_TAG_ATTESTATION_ID_UDID, + HKS_TAG_ATTESTATION_ID_SEC_LEVEL_INFO, + HKS_TAG_ATTESTATION_ID_VERSION_INFO, + HKS_TAG_ATTESTATION_BASE64, + + HKS_TAG_IS_KEY_ALIAS, + HKS_TAG_KEY_STORAGE_FLAG, + HKS_TAG_IS_ALLOWED_WRAP, + HKS_TAG_KEY_WRAP_TYPE, + HKS_TAG_KEY_AUTH_ID, + HKS_TAG_KEY_ROLE, + HKS_TAG_KEY_FLAG, + HKS_TAG_KEY_DOMAIN, + + HKS_TAG_KEY_AUTH_ACCESS_TYPE, + HKS_TAG_KEY_SECURE_SIGN_TYPE, + HKS_TAG_CHALLENGE_TYPE, + HKS_TAG_CHALLENGE_POS, + HKS_TAG_KEY_AUTH_PURPOSE, + + HKS_TAG_KEY_INIT_CHALLENGE, + HKS_TAG_IS_USER_AUTH_ACCESS, + HKS_TAG_USER_AUTH_CHALLENGE, + HKS_TAG_USER_AUTH_ENROLL_ID_INFO, + HKS_TAG_USER_AUTH_SECURE_UID, + HKS_TAG_KEY_AUTH_RESULT, + HKS_TAG_IF_NEED_APPEND_AUTH_INFO, + HKS_TAG_VERIFIED_AUTH_TOKEN, + HKS_TAG_IS_APPEND_UPDATE_DATA, + + HKS_TAG_PROCESS_NAME, + HKS_TAG_PACKAGE_NAME, + HKS_TAG_PAYLOAD_LEN, + HKS_TAG_AE_TAG, + HKS_TAG_CRYPTO_CTX, + HKS_TAG_KEY, + HKS_TAG_KEY_VERSION, + HKS_TAG_IS_KEY_HANDLE, + HKS_TAG_SYMMETRIC_KEY_DATA, + HKS_TAG_ASYMMETRIC_PUBLIC_KEY_DATA, + HKS_TAG_ASYMMETRIC_PRIVATE_KEY_DATA, + HKS_TAG_KEY_ACCESS_TIME, + +}; + +HKS_API_EXPORT enum HksTagType GetTagType(enum HksTag tag) +{ + return (enum HksTagType)((uint32_t)tag & (uint32_t)HKS_TAG_TYPE_MASK); +} + +static bool IsValidTag(uint32_t tag) +{ + uint32_t tagSize = (sizeof(g_validTags)) / (sizeof((g_validTags)[0])); + for (uint32_t i = 0; i < tagSize; ++i) { + if (tag == g_validTags[i]) { + return true; + } + } + return false; +} + +HKS_API_EXPORT int32_t HksCheckParamSetTag(const struct HksParamSet *paramSet) +{ + HKS_IF_NULL_RETURN(paramSet, HKS_ERROR_NULL_POINTER) + + for (uint32_t i = 0; i < paramSet->paramsCnt; ++i) { + uint32_t curTag = paramSet->params[i].tag; + if (!IsValidTag(curTag)) { + HKS_LOG_E("paramSet contains invalid tag! 0x%" LOG_PUBLIC "x", curTag); + return HKS_ERROR_INVALID_ARGUMENT; + } + + for (uint32_t j = i + 1; j < paramSet->paramsCnt; ++j) { + if (curTag == paramSet->params[j].tag) { + HKS_LOG_E("paramSet contains multi-tags! 0x%" LOG_PUBLIC "x", curTag); + return HKS_ERROR_INVALID_ARGUMENT; + } + } + } + + return HKS_SUCCESS; +} + +static int32_t CheckBeforeAddParams(const struct HksParamSet *paramSet, const struct HksParam *params, + uint32_t paramCnt) +{ + if ((params == NULL) || (paramSet == NULL) || (paramSet->paramSetSize > HKS_PARAM_SET_MAX_SIZE) || + (paramCnt > HKS_DEFAULT_PARAM_CNT) || (paramSet->paramsCnt > (HKS_DEFAULT_PARAM_CNT - paramCnt))) { + HKS_LOG_E("invalid params or paramset!"); + return HKS_ERROR_INVALID_ARGUMENT; + } + + for (uint32_t i = 0; i < paramCnt; i++) { + if ((GetTagType((enum HksTag)(params[i].tag)) == HKS_TAG_TYPE_BYTES) && + (params[i].blob.data == NULL)) { + HKS_LOG_E("invalid blob param!"); + return HKS_ERROR_INVALID_ARGUMENT; + } + } + return HKS_SUCCESS; +} + +static int32_t BuildParamSet(struct HksParamSet **paramSet) +{ + struct HksParamSet *freshParamSet = *paramSet; + uint32_t size = freshParamSet->paramSetSize; + uint32_t offset = sizeof(struct HksParamSet) + sizeof(struct HksParam) * freshParamSet->paramsCnt; + + if (size > HKS_DEFAULT_PARAM_SET_SIZE) { + freshParamSet = (struct HksParamSet *)HksMalloc(size); + HKS_IF_NULL_LOGE_RETURN(freshParamSet, HKS_ERROR_MALLOC_FAIL, "malloc params failed!") + + if (memcpy_s(freshParamSet, size, *paramSet, offset) != EOK) { + HKS_FREE_PTR(freshParamSet); + HKS_LOG_E("copy params failed!"); + return HKS_ERROR_INSUFFICIENT_MEMORY; + } + HKS_FREE_PTR(*paramSet); + *paramSet = freshParamSet; + } + + return HksFreshParamSet(freshParamSet, true); +} + +HKS_API_EXPORT int32_t HksFreshParamSet(struct HksParamSet *paramSet, bool isCopy) +{ + HKS_IF_NULL_LOGE_RETURN(paramSet, HKS_ERROR_NULL_POINTER, "invalid NULL paramSet") + + int32_t ret = HksCheckParamSet(paramSet, paramSet->paramSetSize); + HKS_IF_NOT_SUCC_LOGE_RETURN(ret, ret, "invalid fresh paramSet") + + uint32_t size = paramSet->paramSetSize; + uint32_t offset = sizeof(struct HksParamSet) + sizeof(struct HksParam) * paramSet->paramsCnt; + + for (uint32_t i = 0; i < paramSet->paramsCnt; i++) { + if (offset > size) { + HKS_LOG_E("invalid param set offset!"); + return HKS_ERROR_INVALID_ARGUMENT; + } + if (GetTagType((enum HksTag)(paramSet->params[i].tag)) == HKS_TAG_TYPE_BYTES) { + if (IsAdditionOverflow(offset, paramSet->params[i].blob.size)) { + HKS_LOG_E("blob size overflow!"); + return HKS_ERROR_INVALID_ARGUMENT; + } + + if (isCopy && (memcpy_s((uint8_t *)paramSet + offset, size - offset, + paramSet->params[i].blob.data, paramSet->params[i].blob.size) != EOK)) { + HKS_LOG_E("copy param blob failed!"); + return HKS_ERROR_INSUFFICIENT_MEMORY; + } + paramSet->params[i].blob.data = (uint8_t *)paramSet + offset; + offset += paramSet->params[i].blob.size; + } + } + + if (paramSet->paramSetSize != offset) { + HKS_LOG_E("invalid param set size!"); + return HKS_ERROR_INVALID_ARGUMENT; + } + return HKS_SUCCESS; +} + +HKS_API_EXPORT int32_t HksCheckParamSet(const struct HksParamSet *paramSet, uint32_t size) +{ + HKS_IF_NULL_RETURN(paramSet, HKS_ERROR_NULL_POINTER) + + if ((size < sizeof(struct HksParamSet)) || (size > HKS_PARAM_SET_MAX_SIZE) || + (paramSet->paramSetSize != size) || + (paramSet->paramsCnt > ((size - sizeof(struct HksParamSet)) / sizeof(struct HksParam)))) { + HKS_LOG_E("invalid param set!"); + return HKS_ERROR_INVALID_ARGUMENT; + } + return HKS_SUCCESS; +} + +HKS_API_EXPORT int32_t HksInitParamSet(struct HksParamSet **paramSet) +{ + HKS_IF_NULL_LOGE_RETURN(paramSet, HKS_ERROR_NULL_POINTER, "invalid init params!") + + *paramSet = (struct HksParamSet *)HksMalloc(HKS_DEFAULT_PARAM_SET_SIZE); + HKS_IF_NULL_LOGE_RETURN(*paramSet, HKS_ERROR_MALLOC_FAIL, "malloc init param set failed!") + + (*paramSet)->paramsCnt = 0; + (*paramSet)->paramSetSize = sizeof(struct HksParamSet); + return HKS_SUCCESS; +} + +HKS_API_EXPORT int32_t HksAddParams(struct HksParamSet *paramSet, + const struct HksParam *params, uint32_t paramCnt) +{ + int32_t ret = CheckBeforeAddParams(paramSet, params, paramCnt); + HKS_IF_NOT_SUCC_RETURN(ret, ret) + + for (uint32_t i = 0; i < paramCnt; i++) { + paramSet->paramSetSize += sizeof(struct HksParam); + if (GetTagType((enum HksTag)(params[i].tag)) == HKS_TAG_TYPE_BYTES) { + if (IsAdditionOverflow(paramSet->paramSetSize, params[i].blob.size)) { + HKS_LOG_E("params size overflow!"); + paramSet->paramSetSize -= sizeof(struct HksParam); + return HKS_ERROR_INVALID_ARGUMENT; + } + paramSet->paramSetSize += params[i].blob.size; + } + (void)memcpy_s(¶mSet->params[paramSet->paramsCnt++], sizeof(struct HksParam), ¶ms[i], + sizeof(struct HksParam)); + } + return HKS_SUCCESS; +} + +HKS_API_EXPORT int32_t HksBuildParamSet(struct HksParamSet **paramSet) +{ + if ((paramSet == NULL) || (*paramSet == NULL)) { + return HKS_ERROR_NULL_POINTER; + } + + int ret = HksCheckParamSet(*paramSet, (*paramSet)->paramSetSize); + HKS_IF_NOT_SUCC_LOGE_RETURN(ret, ret, "invalid build params!") + + return BuildParamSet(paramSet); +} + +HKS_API_EXPORT void HksFreeParamSet(struct HksParamSet **paramSet) +{ + if (paramSet == NULL) { + HKS_LOG_E("invalid free paramset!"); + return; + } + HKS_FREE_PTR(*paramSet); +} + +static int32_t FreshParamSet(struct HksParamSet *paramSet, bool isCopy) { + uint32_t size = paramSet->paramSetSize; + uint32_t offset = sizeof(struct HksParamSet) + sizeof(struct HksParam) * paramSet->paramsCnt; + + for (uint32_t i = 0; i < paramSet->paramsCnt; i++) { + if (offset > size) { + HKS_LOG_E("invalid param set offset!"); + return HKS_ERROR_INVALID_ARGUMENT; + } + if (GetTagType((enum HksTag)(paramSet->params[i].tag)) == HKS_TAG_TYPE_BYTES) { + if (IsAdditionOverflow(offset, paramSet->params[i].blob.size)) { + HKS_LOG_E("blob size overflow!"); + return HKS_ERROR_INVALID_ARGUMENT; + } + if (isCopy && memcpy_s((uint8_t *)paramSet + offset, size - offset, + paramSet->params[i].blob.data, paramSet->params[i].blob.size) != EOK) { + HKS_LOG_E("copy param blob failed!"); + return HKS_ERROR_INSUFFICIENT_MEMORY; + } + paramSet->params[i].blob.data = (uint8_t *)paramSet + offset; + offset += paramSet->params[i].blob.size; + } + } + + if (paramSet->paramSetSize != offset) { + HKS_LOG_E("invalid param set size!"); + return HKS_ERROR_INVALID_ARGUMENT; + } return HKS_SUCCESS; } -int32_t HksBuildParamSet(struct HksParamSet **paramSet) + +HKS_API_EXPORT int32_t HksGetParam(const struct HksParamSet *paramSet, uint32_t tag, struct HksParam **param) +{ + if ((paramSet == NULL) || (param == NULL)) { + HKS_LOG_E("invalid params!"); + return HKS_ERROR_INVALID_ARGUMENT; + } + + HKS_IF_NOT_SUCC_LOGE_RETURN(HksCheckParamSet(paramSet, paramSet->paramSetSize), + HKS_ERROR_INVALID_ARGUMENT, "invalid paramSet!") + + for (uint32_t i = 0; i < paramSet->paramsCnt; i++) { + if (tag == paramSet->params[i].tag) { + *param = (struct HksParam *)¶mSet->params[i]; + return HKS_SUCCESS; + } + } + + return HKS_ERROR_PARAM_NOT_EXIST; +} + +HKS_API_EXPORT int32_t HksGetParamSet(const struct HksParamSet *inParamSet, + uint32_t inParamSetSize, struct HksParamSet **outParamSet) { + int32_t ret = HksCheckParamSet(inParamSet, inParamSetSize); + HKS_IF_NOT_SUCC_RETURN(ret, ret) + + HKS_IF_NULL_RETURN(outParamSet, HKS_ERROR_NULL_POINTER) + + uint32_t size = inParamSet->paramSetSize; + struct HksParamSet *buf = (struct HksParamSet *)HksMalloc(size); + HKS_IF_NULL_LOGE_RETURN(buf, HKS_ERROR_MALLOC_FAIL, "malloc from param set failed!") + + (void)memcpy_s(buf, size, inParamSet, size); + + ret = FreshParamSet(buf, false); + if (ret != HKS_SUCCESS) { + HKS_FREE_PTR(buf); + return ret; + } + *outParamSet = buf; return HKS_SUCCESS; } -void HksFreeParamSet(struct HksParamSet **paramSet) + +HKS_API_EXPORT int32_t HksCheckParamMatch(const struct HksParam *baseParam, const struct HksParam *param) { + if (baseParam == NULL || param == NULL) { + return HKS_ERROR_NULL_POINTER; + } + if (baseParam->tag != param->tag) { + HKS_LOG_E("unmatch param type!"); + return HKS_ERROR_INVALID_ARGUMENT; + } + + switch (GetTagType((enum HksTag)(baseParam->tag))) { + case HKS_TAG_TYPE_INT: + return (baseParam->int32Param == param->int32Param) ? HKS_SUCCESS : HKS_ERROR_INVALID_ARGUMENT; + case HKS_TAG_TYPE_UINT: + return (baseParam->uint32Param == param->uint32Param) ? HKS_SUCCESS : HKS_ERROR_INVALID_ARGUMENT; + case HKS_TAG_TYPE_ULONG: + return (baseParam->uint64Param == param->uint64Param) ? HKS_SUCCESS : HKS_ERROR_INVALID_ARGUMENT; + case HKS_TAG_TYPE_BOOL: + return (baseParam->boolParam == param->boolParam) ? HKS_SUCCESS : HKS_ERROR_INVALID_ARGUMENT; + case HKS_TAG_TYPE_BYTES: + if (baseParam->blob.size != param->blob.size || + baseParam->blob.data == NULL ||(param->blob.data == NULL)) { + HKS_LOG_E("unmatch byte type len!"); + return HKS_ERROR_INVALID_ARGUMENT; + } + if (HksMemCmp(baseParam->blob.data, param->blob.data, baseParam->blob.size)) { + HKS_LOG_E("unmatch byte type content!"); + return HKS_ERROR_INVALID_ARGUMENT; + } + return HKS_SUCCESS; + default: + HKS_LOG_E("invalid tag type:%" LOG_PUBLIC "x", GetTagType((enum HksTag)(baseParam->tag))); + return HKS_ERROR_INVALID_ARGUMENT; + } } + +HKS_API_EXPORT int32_t HksCheckIsTagAlreadyExist(const struct HksParam *params, uint32_t paramsCnt, + const struct HksParamSet *targetParamSet) +{ + if (params == NULL || targetParamSet == NULL) { + return HKS_ERROR_NULL_POINTER; + } + + int32_t ret = HksCheckParamSet(targetParamSet, targetParamSet->paramSetSize); + HKS_IF_NOT_SUCC_RETURN(ret, ret) + + for (uint32_t i = 0; i < targetParamSet->paramsCnt; ++i) { + for (uint32_t j = 0; j < paramsCnt; ++j) { + if (params[j].tag == targetParamSet->params[i].tag) { + return HKS_ERROR_INVALID_ARGUMENT; + } + } + } + + return HKS_SUCCESS; +} + +HKS_API_EXPORT int32_t HksDeleteTagsFromParamSet(const uint32_t *tag, uint32_t tagCount, + const struct HksParamSet *paramSet, struct HksParamSet **outParamSet) +{ + if (tag == NULL || paramSet == NULL || outParamSet == NULL) { + return HKS_ERROR_NULL_POINTER; + } + int32_t ret = HksFreshParamSet((struct HksParamSet *)paramSet, false); + HKS_IF_NOT_SUCC_LOGE_RETURN(ret, ret, "fresh paramset failed") + + struct HksParamSet *newParamSet = NULL; + ret = HksInitParamSet(&newParamSet); + HKS_IF_NOT_SUCC_LOGE_RETURN(ret, ret, "init param set failed") + + for (uint32_t i = 0; i < paramSet->paramsCnt; ++i) { + bool isDeleteTag = false; + for (uint32_t j = 0; j < tagCount; ++j) { + if (paramSet->params[i].tag == tag[j]) { + isDeleteTag = true; + break; + } + } + if (!isDeleteTag) { + ret = HksAddParams(newParamSet, ¶mSet->params[i], 1); + if (ret != HKS_SUCCESS) { + HksFreeParamSet(&newParamSet); + return ret; + } + } + } + + ret = HksBuildParamSet(&newParamSet); + if (ret != HKS_SUCCESS) { + HksFreeParamSet(&newParamSet); + return ret; + } + + *outParamSet = newParamSet; + return HKS_SUCCESS; +} + int32_t HksInit(const struct HksBlob *keyAlias, const struct HksParamSet *paramSet, struct HksBlob *handle, struct HksBlob *token) { @@ -41,8 +506,8 @@ int32_t HksUpdate(const struct HksBlob *handle, const struct HksParamSet *paramS const struct HksBlob *inData, struct HksBlob *outData) { size_t size = std::min(outData->size, inData->size); - (void)memcpy_s(outData->data, outData->size, inData->data, size); outData->size = size; + (void)memcpy_s(outData->data, outData->size, inData->data, size); return HKS_SUCCESS; } @@ -63,32 +528,51 @@ void HksFree(void *ptr) } -int32_t HksGetParamSet(const struct HksParamSet *fromParamSet, uint32_t fromParamSetSize, struct HksParamSet **paramSet) -{ - return 0; -} -int32_t HksGetParam(const struct HksParamSet *paramSet, uint32_t tag, struct HksParam **param) +int32_t HksLocalGenerateKey(const struct HksParamSet *paramSetIn, struct HksParamSet *paramSetOut) { + paramSetOut->paramSetSize = paramSetIn->paramSetSize; + paramSetOut->paramsCnt = paramSetIn->paramsCnt; +// (void)memcpy_s(paramSetIn->params, paramSetIn->paramSetSize, paramSetOut->params, paramSetOut->paramSetSize); + HksMemCmp(paramSetIn->params, paramSetOut->params, paramSetOut->paramSetSize); return 0; } -int32_t HksFreshParamSet(struct HksParamSet *paramSet, bool isCopy) -{ - return 0; -} -int32_t HksCheckParamSetTag(const struct HksParamSet *paramSet) -{ - return 0; -} -int32_t HksCheckParamSet(const struct HksParamSet *paramSet, uint32_t size) + +int32_t HksClientGenerateKey(const struct HksBlob *keyAlias, const struct HksParamSet *paramSetIn, struct HksParamSet *paramSetOut) { + std::string key((char *)keyAlias->data); + KEYS.insert(key); + if (paramSetOut == nullptr) { + return 0; + } + paramSetOut->paramSetSize = paramSetIn->paramSetSize; + paramSetOut->paramsCnt = paramSetIn->paramsCnt; + HksMemCmp(paramSetIn->params, paramSetOut->params, paramSetOut->paramSetSize); return 0; } -int32_t HksCheckParamMatch(const struct HksParam *baseParam, const struct HksParam *param) + +int32_t HksGenerateKey(const struct HksBlob *keyAlias, const struct HksParamSet *paramSetIn, + struct HksParamSet *paramSetOut) { - return 0; + HKS_LOG_I("enter generate key"); + struct HksParam *storageFlag = NULL; + int32_t ret = HksGetParam(paramSetIn, HKS_TAG_KEY_STORAGE_FLAG, &storageFlag); + if ((ret == HKS_SUCCESS) && (storageFlag->uint32Param == HKS_STORAGE_TEMP)) { + if ((paramSetIn == NULL) || (paramSetOut == NULL)) { + return HKS_ERROR_NULL_POINTER; + } + ret = HksLocalGenerateKey(paramSetIn, paramSetOut); + HKS_LOG_I("leave generate temp key, result = %" LOG_PUBLIC "d", ret); + return ret; + } + + /* generate persistent keys */ + if ((paramSetIn == NULL) || (keyAlias == NULL)) { + return HKS_ERROR_NULL_POINTER; + } + ret = HksClientGenerateKey(keyAlias, paramSetIn, paramSetOut); + HKS_LOG_I("leave generate persistent key, result = %" LOG_PUBLIC "d", ret); + return ret; } -int32_t HksGenerateKey(const struct HksBlob *keyAlias, - const struct HksParamSet *paramSetIn, struct HksParamSet *paramSetOut) { return 0; } int32_t HksGetSdkVersion(struct HksBlob *sdkVersion) { return 0; @@ -120,7 +604,8 @@ int32_t HksGetKeyParamSet(const struct HksBlob *keyAlias, const struct HksParamS } int32_t HksKeyExist(const struct HksBlob *keyAlias, const struct HksParamSet *paramSet) { - return 0; + std::string key((char *)keyAlias->data); + return KEYS.find(key) != KEYS.end() ? 0 : HKS_ERROR_NOT_EXIST; } int32_t HksGenerateRandom(const struct HksParamSet *paramSet, struct HksBlob *random) { @@ -139,23 +624,27 @@ int32_t HksVerify(const struct HksBlob *key, const struct HksParamSet *paramSet, int32_t HksEncrypt(const struct HksBlob *key, const struct HksParamSet *paramSet, const struct HksBlob *plainText, struct HksBlob *cipherText) { - if(plainText->size == 0) { + if (plainText->size == 0) { return HKS_ERROR_INVALID_ARGUMENT; } (void)memcpy_s(cipherText->data, cipherText->size, plainText->data, plainText->size); // cipherText->size = plainText->size; cipherText->size = 48; + cipherText->data[cipherText->size - 1] = 66; return 0; } int32_t HksDecrypt(const struct HksBlob *key, const struct HksParamSet *paramSet, const struct HksBlob *cipherText, struct HksBlob *plainText) { - if(cipherText->size == 0) { + if (cipherText->size == 0) { return HKS_ERROR_INVALID_ARGUMENT; } - (void)memcpy_s(plainText->data, plainText->size, cipherText->data, cipherText->size); - // plainText->size = cipherText->size; plainText->size = 32; + if (cipherText->data[cipherText->size - 1] != 66) { + return HKS_ERROR_INVALID_ARGUMENT; + } + (void)memcpy_s(plainText->data, plainText->size, cipherText->data, plainText->size); + // plainText->size = cipherText->size; return 0; } int32_t HksAgreeKey(const struct HksParamSet *paramSet, const struct HksBlob *privateKey, diff --git a/mock/src/mock_ipc.cpp b/mock/src/mock_ipc.cpp index 38a2cd7a..5c8f16aa 100644 --- a/mock/src/mock_ipc.cpp +++ b/mock/src/mock_ipc.cpp @@ -26,33 +26,88 @@ namespace OHOS { BrokerRegistration &BrokerRegistration::Get() { - static OHOS::BrokerRegistration brokerRegistration; - return brokerRegistration; -}; + static BrokerRegistration instance; + return instance; +} -bool BrokerRegistration::Register(const std::u16string &descriptor, const BrokerRegistration::Constructor &creator) +BrokerRegistration::~BrokerRegistration() { - creators_[descriptor] = creator; - return true; + isUnloading = true; + std::lock_guard lockGuard(creatorMutex_); + for (auto it = creators_.begin(); it != creators_.end();) { + it = creators_.erase(it); + } + for (auto it1 = objects_.begin(); it1 != objects_.end();) { + BrokerDelegatorBase *object = reinterpret_cast(*it1); + object->isSoUnloaded = true; + it1 = objects_.erase(it1); + } +} + +bool BrokerRegistration::Register(const std::u16string &descriptor, const Constructor &creator, + const BrokerDelegatorBase *object) +{ + if (descriptor.empty()) { + return false; + } + + std::lock_guard lockGuard(creatorMutex_); + auto it = creators_.find(descriptor); + bool ret = false; + if (it == creators_.end()) { + ret = creators_.insert({ descriptor, creator }).second; + } + auto it1 = std::find_if(objects_.begin(), objects_.end(), [descriptor](uintptr_t id) { + const BrokerDelegatorBase *object = reinterpret_cast(id); + return object->descriptor_ == descriptor; + }); + if (it1 == objects_.end()) { + objects_.push_back(reinterpret_cast(object)); + } + return ret; } void BrokerRegistration::Unregister(const std::u16string &descriptor) { - creators_.erase(descriptor); + if (isUnloading) { +// ZLOGE(LABEL, "BrokerRegistration is Unloading"); + return; + } + std::lock_guard lockGuard(creatorMutex_); + if (!descriptor.empty()) { + auto it = creators_.find(descriptor); + if (it != creators_.end()) { + creators_.erase(it); + } + auto it1 = std::find_if(objects_.begin(), objects_.end(), [descriptor](uintptr_t id) { + const BrokerDelegatorBase *object = reinterpret_cast(id); + return object->descriptor_ == descriptor; + }); + if (it1 != objects_.end()) { + objects_.erase(it1); + } + } } sptr BrokerRegistration::NewInstance(const std::u16string &descriptor, const sptr &object) { - if (object == nullptr) { - return nullptr; - } - if (creators_.find(descriptor) == creators_.end()) { - return nullptr; + std::lock_guard lockGuard(creatorMutex_); + + sptr broker; + if (object != nullptr) { + auto it = creators_.find(descriptor); + if (it != creators_.end()) { + broker = it->second(object); + } +// if (object->IsProxyObject()) { +// +// } else { +// broker = object->AsInterface().GetRefPtr(); +// } } - return creators_[descriptor](object); + return broker; } -BrokerRegistration::~BrokerRegistration() {} PeerHolder::PeerHolder(const sptr &object) : remoteObject_(object) {}; sptr PeerHolder::Remote() { return remoteObject_; } diff --git a/mock/src/mock_ipc_object_stub.cpp b/mock/src/mock_ipc_object_stub.cpp index 96152970..99cd67e1 100644 --- a/mock/src/mock_ipc_object_stub.cpp +++ b/mock/src/mock_ipc_object_stub.cpp @@ -83,30 +83,10 @@ int32_t IPCObjectStub::InvokerDataBusThread(MessageParcel &data, MessageParcel & { return 0; } -int32_t IPCObjectStub::IncStubRefs(MessageParcel &data, MessageParcel &reply) -{ - return 0; -} -int32_t IPCObjectStub::DecStubRefs(MessageParcel &data, MessageParcel &reply) -{ - return 0; -} int32_t IPCObjectStub::AddAuthInfo(MessageParcel &data, MessageParcel &reply, uint32_t code) { return 0; } -int32_t IPCObjectStub::GrantDataBusName(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) -{ - return 0; -} -std::string IPCObjectStub::CreateDatabusName(int uid, int pid) -{ - return std::string(); -} -std::string IPCObjectStub::GetDataBusName() -{ - return std::string(); -} bool IPCObjectStub::IsDeviceIdIllegal(const std::string &deviceID) { return false; diff --git a/mock/src/mock_js_runtime.cpp b/mock/src/mock_js_runtime.cpp index 7f44cec3..c24b8f87 100644 --- a/mock/src/mock_js_runtime.cpp +++ b/mock/src/mock_js_runtime.cpp @@ -15,6 +15,7 @@ #include "js_runtime.h" #include "js_runtime_utils.h" #include "js_extension_context.h" +#include "extra_params.h" namespace OHOS::AbilityRuntime { HandleScope::HandleScope(JsRuntime& jsRuntime) {} HandleScope::HandleScope(NativeEngine &engine) {} @@ -27,8 +28,64 @@ NativeValue* HandleEscape::Escape(NativeValue* value) { return value; } std::unique_ptr JsRuntime::Create(const Options& options) { class JsRuntimeInner : public JsRuntime { public: - bool RunScript(const std::string &path) override { return false; } - void StartDebugMode(bool needBreakPoint, int32_t instanceId) override {} +// bool RunScript(const std::string &path) override { return false; } +// void StartDebugMode(bool needBreakPoint, int32_t instanceId) override {} + Language GetLanguage() const override + { + return JsRuntime::GetLanguage(); + } + void DumpHeapSnapshot(bool isPrivate) override + { + JsRuntime::DumpHeapSnapshot(isPrivate); + } + void NotifyApplicationState(bool isBackground) override + { + JsRuntime::NotifyApplicationState(isBackground); + } + void StartDebugMode(bool needBreakPoint) override + { + JsRuntime::StartDebugMode(needBreakPoint); + } + void PreloadSystemModule(const string &moduleName) override + { + JsRuntime::PreloadSystemModule(moduleName); + } + void FinishPreload() override + { + JsRuntime::FinishPreload(); + } + bool LoadRepairPatch(const string &patchFile, const string &baseFile) override + { + return JsRuntime::LoadRepairPatch(patchFile, baseFile); + } + bool NotifyHotReloadPage() override + { + return JsRuntime::NotifyHotReloadPage(); + } + bool UnLoadRepairPatch(const string &patchFile) override + { + return JsRuntime::UnLoadRepairPatch(patchFile); + } + void UpdateExtensionType(int32_t extensionType) override + { + JsRuntime::UpdateExtensionType(extensionType); + } + void RegisterQuickFixQueryFunc(const std::map &moduleAndPath) override + { + JsRuntime::RegisterQuickFixQueryFunc(moduleAndPath); + } + ~JsRuntimeInner() override = default; + + protected: + bool Initialize(const Options &options) override + { + return JsRuntime::Initialize(options); + } + NativeValue *LoadJsBundle(const string &path) override + { + return JsRuntime::LoadJsBundle(path); + } + protected: NativeValue *LoadJsModule(const std::string &path) override { return nullptr;} }; @@ -42,12 +99,7 @@ std::unique_ptr JsRuntime::LoadSystemModuleByEngine(NativeEngin return std::unique_ptr(); } std::unique_ptr JsRuntime::LoadModule(const std::string &moduleName, const std::string &modulePath, - bool esmodule) -{ - return std::unique_ptr(); -} -std::unique_ptr JsRuntime::LoadModule(const std::string &moduleName, const std::string &modulePath, - bool hapPath, bool esmodule) + const std::string &hapPath, bool esmodule, bool useCommonChunk) { return std::unique_ptr(); } @@ -59,12 +111,29 @@ std::unique_ptr JsRuntime::LoadSystemModule(const std::string & void JsRuntime::PostTask(const std::function &task, const std::string &name, int64_t delayTime) {} void JsRuntime::RemoveTask(const std::string &name) {} void JsRuntime::DumpHeapSnapshot(bool isPrivate) {} -std::string JsRuntime::BuildJsStackTrace() { return ""; } void JsRuntime::NotifyApplicationState(bool isBackground) {} -bool JsRuntime::RunSandboxScript(const std::string &path) { return false; } +//bool JsRuntime::RunSandboxScript(const std::string &path) { return false; } bool JsRuntime::Initialize(const Runtime::Options &options) { return false; } void JsRuntime::Deinitialize() {} NativeValue *JsRuntime::LoadJsBundle(const std::string &path) { return nullptr;} +void JsRuntime::StartDebugMode(bool needBreakPoint) {} +void JsRuntime::PreloadSystemModule(const std::string &moduleName) {} +void JsRuntime::FinishPreload() {} +bool JsRuntime::LoadRepairPatch(const std::string &patchFile, const std::string &baseFile) +{ + return false; +} +bool JsRuntime::NotifyHotReloadPage() +{ + return false; +} +bool JsRuntime::UnLoadRepairPatch(const std::string &patchFile) +{ + return false; +} +void JsRuntime::UpdateExtensionType(int32_t extensionType) {} +void JsRuntime::RegisterQuickFixQueryFunc(const std::map& moduleAndPath) {} + NativeValue* CreateJsExtensionContext(NativeEngine& engine, const std::shared_ptr& context, std::shared_ptr abilityInfo, DetachCallback detach, AttachCallback attach) { return nullptr; } diff --git a/preferences/interfaces/inner_api/BUILD.gn b/preferences/interfaces/inner_api/BUILD.gn index e0210d6b..1133cb29 100644 --- a/preferences/interfaces/inner_api/BUILD.gn +++ b/preferences/interfaces/inner_api/BUILD.gn @@ -21,7 +21,7 @@ config("native_preferences_config") { } config("native_preferences_public_config") { - visibility = [ "//foundation/distributeddatamgr/preferences:*" ] + visibility = [ ":*" ] include_dirs = [ "include" ] } diff --git a/relational_store/bundle.json b/relational_store/bundle.json index 1e2b3fda..6b9df4d3 100644 --- a/relational_store/bundle.json +++ b/relational_store/bundle.json @@ -71,6 +71,7 @@ "//foundation/distributeddatamgr/relational_store/interfaces/inner_api/dataability:native_dataability", "//foundation/distributeddatamgr/relational_store/interfaces/inner_api/rdb_data_share_adapter:rdb_data_share_adapter", "//foundation/distributeddatamgr/relational_store/interfaces/inner_api/rdb:native_rdb", + "//foundation/distributeddatamgr/relational_store/interfaces/inner_api/cloud_data:cloud_data", "//foundation/distributeddatamgr/relational_store/frameworks/js/napi/dataability:dataability", "//foundation/distributeddatamgr/relational_store/frameworks/js/napi/rdb:rdb", "//foundation/distributeddatamgr/relational_store/frameworks/js/napi/rdb:napi_rdb", @@ -136,6 +137,16 @@ ], "header_base": "//foundation/distributeddatamgr/relational_store/interfaces/inner_api/rdb_data_ability_adapter/include" } + }, + { + "name": "//foundation/distributeddatamgr/relational_store/interfaces/inner_api/cloud_data:cloud_data", + "header": { + "header_files": [ + "cloud_manager.h", + "cloud_service.h" + ], + "header_base": "//foundation/distributeddatamgr/relational_store/interfaces/inner_api/cloud_data/include" + } } ], "test": [ diff --git a/relational_store/frameworks/native/rdb/include/rdb_manager_impl.h b/relational_store/frameworks/native/rdb/include/rdb_manager_impl.h index 80689b3d..22150516 100644 --- a/relational_store/frameworks/native/rdb/include/rdb_manager_impl.h +++ b/relational_store/frameworks/native/rdb/include/rdb_manager_impl.h @@ -33,13 +33,12 @@ class RdbServiceProxy; class RdbStoreDataServiceProxy; class RdbManagerImpl { public: - static constexpr int GET_SA_RETRY_TIMES = 3; static constexpr int RETRY_INTERVAL = 1; static constexpr int WAIT_TIME = 2; static RdbManagerImpl &GetInstance(); - int GetRdbService(const std::string& bundleName, const std::string& storeName, std::shared_ptr &service); + int GetRdbService(const std::string& bundleName, std::shared_ptr &service); void OnRemoteDied(); diff --git a/relational_store/frameworks/native/rdb/include/rdb_service_proxy.h b/relational_store/frameworks/native/rdb/include/rdb_service_proxy.h index 43099c5a..aae0965d 100644 --- a/relational_store/frameworks/native/rdb/include/rdb_service_proxy.h +++ b/relational_store/frameworks/native/rdb/include/rdb_service_proxy.h @@ -57,7 +57,7 @@ public: void ImportObservers(ObserverMap& observers); /*CLoudData*/ - int32_t OpenStore(const CloudParam &cloudParam) override; + int32_t GetSchema(const std::string &bundleName, const std::string &storeName) override; protected: int32_t DoSync(const RdbSyncerParam& param, const SyncOption& option, const RdbPredicates& predicates, SyncResult& result) override; diff --git a/relational_store/frameworks/native/rdb/src/abs_rdb_predicates.cpp b/relational_store/frameworks/native/rdb/src/abs_rdb_predicates.cpp index 9086980f..4d32ba9a 100644 --- a/relational_store/frameworks/native/rdb/src/abs_rdb_predicates.cpp +++ b/relational_store/frameworks/native/rdb/src/abs_rdb_predicates.cpp @@ -18,10 +18,6 @@ #include "abs_rdb_predicates.h" #include "logger.h" #include "rdb_trace.h" -#if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) -#include "rdb_manager.h" -#include "rdb_service.h" -#endif namespace OHOS::NativeRdb { AbsRdbPredicates::AbsRdbPredicates(std::string tableName) diff --git a/relational_store/frameworks/native/rdb/src/rdb_manager.cpp b/relational_store/frameworks/native/rdb/src/rdb_manager.cpp deleted file mode 100644 index 6dc545b8..00000000 --- a/relational_store/frameworks/native/rdb/src/rdb_manager.cpp +++ /dev/null @@ -1,24 +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. - */ - -#include "rdb_manager.h" -#include "rdb_manager_impl.h" - -namespace OHOS::DistributedRdb { -int RdbManager::GetRdbService(const RdbSyncerParam ¶m, std::shared_ptr &service) -{ - return RdbManagerImpl::GetInstance().GetRdbService(param.bundleName_, param.storeName_, service); -} -} // namespace OHOS::DistributedRdb diff --git a/relational_store/frameworks/native/rdb/src/rdb_manager_impl.cpp b/relational_store/frameworks/native/rdb/src/rdb_manager_impl.cpp index 3fc093dd..0e38609f 100644 --- a/relational_store/frameworks/native/rdb/src/rdb_manager_impl.cpp +++ b/relational_store/frameworks/native/rdb/src/rdb_manager_impl.cpp @@ -80,7 +80,7 @@ RdbManagerImpl& RdbManagerImpl::GetInstance() return manager; } -int RdbManagerImpl::GetRdbService(const std::string& bundleName, const std::string& storeName, std::shared_ptr &service) +int RdbManagerImpl::GetRdbService(const std::string& bundleName, std::shared_ptr &service) { std::lock_guard lock(mutex_); if (rdbService_ != nullptr) { @@ -95,13 +95,13 @@ int RdbManagerImpl::GetRdbService(const std::string& bundleName, const std::stri return E_ERROR; } - auto remote = distributedDataMgr_->GetFeatureInterface("relational_store"); + auto remote = distributedDataMgr_->GetFeatureInterface(DistributedRdb::RdbService::SERVICE_NAME); if (remote == nullptr) { ZLOGE("get rdb service failed"); return E_NOT_SUPPORTED; } sptr serviceProxy = iface_cast(remote); - if (serviceProxy->InitNotifier(bundleName, storeName) != RDB_OK) { + if (serviceProxy->InitNotifier(bundleName) != RDB_OK) { ZLOGE("init notifier failed"); return E_ERROR; } @@ -131,7 +131,7 @@ void RdbManagerImpl::OnRemoteDied() RdbSyncerParam param; param.bundleName_ = bundleName_; std::shared_ptr service = nullptr; - int errCode = GetRdbService(bundleName_, "", service); + int errCode = GetRdbService(bundleName_, service); if (errCode != E_OK) { return; } diff --git a/relational_store/frameworks/native/rdb/src/rdb_service_proxy.cpp b/relational_store/frameworks/native/rdb/src/rdb_service_proxy.cpp index 04388259..0a14377d 100644 --- a/relational_store/frameworks/native/rdb/src/rdb_service_proxy.cpp +++ b/relational_store/frameworks/native/rdb/src/rdb_service_proxy.cpp @@ -339,13 +339,13 @@ int32_t RdbServiceProxy::DestroyRDBTable(const RdbSyncerParam ¶m) return status; } -int32_t RdbServiceProxy::OpenStore(const CloudParam &cloudParam) +int32_t RdbServiceProxy::GetSchema(const std::string &bundleName, const std::string &storeName) { MessageParcel reply; - int32_t status = IPC_SEND(RDB_SERVICE_CMD_OPEN_STORE, reply, cloudParam); + int32_t status = IPC_SEND(RDB_SERVICE_CMD_GET_SCHEMA, reply, bundleName, storeName); if (status != RDB_OK) { - ZLOGE("status:%{public}d, bundleName:%{public}s, storeName:%{public}s", status, cloudParam.bundleName.c_str(), - cloudParam.storeName.c_str()); + ZLOGE("status:%{public}d, bundleName:%{public}s, storeName:%{public}s", status, bundleName.c_str(), + storeName.c_str()); } return status; } diff --git a/relational_store/frameworks/native/rdb/src/rdb_store_config.cpp b/relational_store/frameworks/native/rdb/src/rdb_store_config.cpp index ad764efd..23b61174 100644 --- a/relational_store/frameworks/native/rdb/src/rdb_store_config.cpp +++ b/relational_store/frameworks/native/rdb/src/rdb_store_config.cpp @@ -391,25 +391,4 @@ void RdbStoreConfig::ClearEncryptKey() { encryptKey_.assign(encryptKey_.size(), 0); } - -void RdbStoreConfig::SetVersion(int32_t version) -{ - schemaVerion_ = version; - -} - -int32_t RdbStoreConfig::GetVersion() const -{ - return schemaVerion_; -} - -void RdbStoreConfig::SetCloudId(std::string cloudId) -{ - cloudId_ = cloudId; -} - -std::string RdbStoreConfig::GetCloudId() const -{ - return cloudId_; -} } // namespace OHOS::NativeRdb diff --git a/relational_store/frameworks/native/rdb/src/rdb_store_impl.cpp b/relational_store/frameworks/native/rdb/src/rdb_store_impl.cpp index f866243c..5c09002f 100644 --- a/relational_store/frameworks/native/rdb/src/rdb_store_impl.cpp +++ b/relational_store/frameworks/native/rdb/src/rdb_store_impl.cpp @@ -37,7 +37,7 @@ #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) #include "iresult_set.h" #include "rdb_device_manager_adapter.h" -#include "rdb_manager.h" +#include "rdb_manager_impl.h" #include "relational_store_manager.h" #include "rdb_security_manager.h" #include "result_set_proxy.h" @@ -88,15 +88,22 @@ int RdbStoreImpl::InnerOpen(const RdbStoreConfig &config) syncerParam_.type_ = config.GetDistributedType(); syncerParam_.isEncrypt_ = config.IsEncrypt(); syncerParam_.password_ = {}; - // open uri share + std::shared_ptr service = nullptr; + errCode = DistributedRdb::RdbManagerImpl::GetInstance().GetRdbService(config.GetBundleName(), service); + if (errCode != E_OK) { + LOG_ERROR("RdbStoreImpl::InnerOpen get service failed, err is %{public}d.", errCode); + return E_OK; + } + + errCode = service->GetSchema(config.GetBundleName(), config.GetName()); + if (errCode != E_OK) { + LOG_ERROR("RdbStoreImpl::InnerOpen GetSchema failed, err is %{public}d.", errCode); + return E_OK; + } + + // open uri share if (!config.GetUri().empty()) { - std::shared_ptr service = nullptr; - errCode = DistributedRdb::RdbManager::GetRdbService(syncerParam_, service); - if (errCode != E_OK) { - LOG_ERROR("RdbStoreImpl::InnerOpen get service failed, err is %{public}d.", errCode); - return E_OK; - } errCode = service->CreateRDBTable(syncerParam_, config.GetWritePermission(), config.GetReadPermission()); if (errCode != E_OK) { LOG_ERROR("RdbStoreImpl::InnerOpen service CreateRDBTable failed"); @@ -105,21 +112,6 @@ int RdbStoreImpl::InnerOpen(const RdbStoreConfig &config) isShared_ = true; } - if(config.GetVersion() >= 0){ - std::shared_ptr service = nullptr; - errCode = DistributedRdb::RdbManager::GetRdbService(syncerParam_, service); - if (errCode != E_OK) { - LOG_ERROR("RdbStoreImpl::InnerOpen get service failed, err is %{public}d.", errCode); - return E_OK; - } - DistributedRdb::CloudParam cloudParam = { config.GetBundleName(), config.GetName(), config.GetCloudId(), - config.GetVersion() }; - errCode = service->OpenStore(cloudParam); - if (errCode != E_OK) { - LOG_ERROR("RdbStoreImpl::InnerOpen OpenStore failed, err is %{public}d.", errCode); - return E_OK; - } - } #endif return E_OK; } @@ -136,7 +128,7 @@ RdbStoreImpl::~RdbStoreImpl() #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) if (isShared_) { std::shared_ptr service = nullptr; - int errCode = DistributedRdb::RdbManager::GetRdbService(syncerParam_, service); + int errCode = DistributedRdb::RdbManagerImpl::GetInstance().GetRdbService(syncerParam_.bundleName_, service); if (errCode != E_OK) { LOG_ERROR("RdbStoreImpl::~RdbStoreImpl get service failed"); return; @@ -415,7 +407,7 @@ std::shared_ptr RdbStoreImpl::RemoteQuery(const std::string &device, std::vector selectionArgs = predicates.GetWhereArgs(); std::string sql = SqliteSqlBuilder::BuildQueryString(predicates, columns); std::shared_ptr service = nullptr; - errCode = DistributedRdb::RdbManager::GetRdbService(syncerParam_, service); + errCode = DistributedRdb::RdbManagerImpl::GetInstance().GetRdbService(syncerParam_.bundleName_, service); if (errCode != E_OK) { LOG_ERROR("RdbStoreImpl::RemoteQuery get service failed"); return nullptr; @@ -1101,7 +1093,7 @@ int RdbStoreImpl::SetDistributedTables(const std::vector &tables) } std::shared_ptr service = nullptr; - int errCode = DistributedRdb::RdbManager::GetRdbService(syncerParam_, service); + int errCode = DistributedRdb::RdbManagerImpl::GetInstance().GetRdbService(syncerParam_.bundleName_, service); if (errCode != E_OK) { return errCode; } @@ -1147,7 +1139,7 @@ int RdbStoreImpl::Sync(const SyncOption &option, const AbsRdbPredicates &predica { DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__)); std::shared_ptr service = nullptr; - int errCode = DistributedRdb::RdbManager::GetRdbService(syncerParam_, service); + int errCode = DistributedRdb::RdbManagerImpl::GetInstance().GetRdbService(syncerParam_.bundleName_, service); if (errCode != E_OK) { LOG_ERROR("GetRdbService is failed, err is %{public}d.", errCode); return errCode; @@ -1163,7 +1155,7 @@ int RdbStoreImpl::Sync(const SyncOption &option, const AbsRdbPredicates &predica int RdbStoreImpl::Subscribe(const SubscribeOption &option, RdbStoreObserver *observer) { std::shared_ptr service = nullptr; - int errCode = DistributedRdb::RdbManager::GetRdbService(syncerParam_, service); + int errCode = DistributedRdb::RdbManagerImpl::GetInstance().GetRdbService(syncerParam_.bundleName_, service); if (errCode != E_OK) { return errCode; } @@ -1174,7 +1166,7 @@ int RdbStoreImpl::UnSubscribe(const SubscribeOption &option, RdbStoreObserver *o { LOG_INFO("enter"); std::shared_ptr service = nullptr; - int errCode = DistributedRdb::RdbManager::GetRdbService(syncerParam_, service); + int errCode = DistributedRdb::RdbManagerImpl::GetInstance().GetRdbService(syncerParam_.bundleName_, service); if (errCode != E_OK) { return errCode; } diff --git a/relational_store/interfaces/inner_api/cloud_data/BUILD.gn b/relational_store/interfaces/inner_api/cloud_data/BUILD.gn new file mode 100644 index 00000000..248fab0d --- /dev/null +++ b/relational_store/interfaces/inner_api/cloud_data/BUILD.gn @@ -0,0 +1,67 @@ +# 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. +import("//build/ohos.gni") +import("//foundation/distributeddatamgr/relational_store/relational_store.gni") + +config("cloud_data_config") { + visibility = [ ":*" ] + + include_dirs = [ + "include", + "${cloud_data_native_path}/include", + "${relational_store_innerapi_path}/rdb/include", + "//utils/system/safwk/native/include", + "//foundation/communication/ipc/interfaces/innerkits/ipc_core/include", + "//foundation/distributeddatamgr/kv_store/frameworks/common", + ] + + defines = [ + "RELATIONAL_STORE", + "SQLITE_HAS_CODEC", + ] +} + +base_sources = [ + "${cloud_data_native_path}/src/cloud_manager.cpp", + "${cloud_data_native_path}/src/cloud_service_proxy.cpp", + "${cloud_data_native_path}/src/cloud_types_util.cpp", +] + +ohos_shared_library("cloud_data") { + part_name = "relational_store" + sources = base_sources + + configs = [ ":cloud_data_config" ] + + deps = [ + "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb:distributeddb", + "//third_party/sqlite:sqlite", + ] + ldflags = [ "-Wl,--exclude-libs,ALL" ] + cflags_cc = [ "-fvisibility=hidden" ] + + sources += [] + + public_deps = [ "${relational_store_innerapi_path}/appdatafwk:native_appdatafwk" ] + + external_deps = [ + "c_utils:utils", + "hilog_native:libhilog", + "hitrace_native:hitrace_meter", + "ipc:ipc_core", + "samgr:samgr_proxy", + ] + + innerapi_tags = [ "platformsdk" ] + subsystem_name = "distributeddatamgr" +} diff --git a/relational_store/interfaces/inner_api/cloud_data/include/cloud_manager.h b/relational_store/interfaces/inner_api/cloud_data/include/cloud_manager.h index 8dcc165f..132016bf 100644 --- a/relational_store/interfaces/inner_api/cloud_data/include/cloud_manager.h +++ b/relational_store/interfaces/inner_api/cloud_data/include/cloud_manager.h @@ -19,8 +19,9 @@ #include #include "cloud_service.h" +#include "rdb_visibility.h" namespace OHOS::CloudData { -class CloudManager { +class RDB_API_EXPORT CloudManager { public: static CloudManager &GetInstance(); std::shared_ptr GetCloudService(); diff --git a/relational_store/interfaces/inner_api/cloud_data/include/cloud_service.h b/relational_store/interfaces/inner_api/cloud_data/include/cloud_service.h index e1645330..83792cf6 100644 --- a/relational_store/interfaces/inner_api/cloud_data/include/cloud_service.h +++ b/relational_store/interfaces/inner_api/cloud_data/include/cloud_service.h @@ -18,8 +18,9 @@ #include #include #include +#include "rdb_visibility.h" namespace OHOS::CloudData { -class CloudService { +class RDB_API_EXPORT CloudService { public: enum TransId : int32_t { @@ -56,13 +57,12 @@ public: IPC_PARCEL_ERROR }; - struct StoreInfo { + struct RDB_API_EXPORT StoreInfo { std::string bundleName; std::string storeId; int32_t version; }; - static constexpr const char *SERVICE_NAME = "cloud"; virtual ~CloudService() = default; virtual int32_t EnableCloud(const std::string &id, const std::map &switches) = 0; virtual int32_t DisableCloud(const std::string &id) = 0; @@ -71,6 +71,8 @@ public: virtual int32_t NotifyDataChange(const std::string &id, const std::string &bundleName) = 0; virtual int32_t Config(const std::string &id, const StoreInfo &storeInfo, std::string &schema) = 0; virtual int32_t ClearConfig(const std::string &id, const StoreInfo &storeInfo) = 0; + + static constexpr const char *SERVICE_NAME = "cloud"; }; } // namespace OHOS::CloudData #endif // OHOS_DISTRIBUTED_DATA_CLOUD_CLOUD_SERVICE_H diff --git a/relational_store/interfaces/inner_api/rdb/BUILD.gn b/relational_store/interfaces/inner_api/rdb/BUILD.gn index 39b20a8b..4003c7ef 100644 --- a/relational_store/interfaces/inner_api/rdb/BUILD.gn +++ b/relational_store/interfaces/inner_api/rdb/BUILD.gn @@ -151,7 +151,6 @@ ohos_shared_library("native_rdb") { sources += [ "${relational_store_native_path}/rdb/src/abs_shared_result_set.cpp", - "${relational_store_native_path}/rdb/src/rdb_manager.cpp", "${relational_store_native_path}/rdb/src/rdb_manager_impl.cpp", "${relational_store_native_path}/rdb/src/rdb_notifier_stub.cpp", "${relational_store_native_path}/rdb/src/rdb_security_manager.cpp", @@ -215,7 +214,6 @@ ohos_static_library("native_rdb_static") { sources += [ "${relational_store_native_path}/rdb/src/abs_shared_result_set.cpp", - "${relational_store_native_path}/rdb/src/rdb_manager.cpp", "${relational_store_native_path}/rdb/src/rdb_manager_impl.cpp", "${relational_store_native_path}/rdb/src/rdb_notifier_stub.cpp", "${relational_store_native_path}/rdb/src/rdb_security_manager.cpp", diff --git a/relational_store/interfaces/inner_api/rdb/include/rdb_service.h b/relational_store/interfaces/inner_api/rdb/include/rdb_service.h index 9e1699be..d4e66dad 100644 --- a/relational_store/interfaces/inner_api/rdb/include/rdb_service.h +++ b/relational_store/interfaces/inner_api/rdb/include/rdb_service.h @@ -37,7 +37,7 @@ public: RDB_SERVICE_CMD_REMOTE_QUERY, RDB_SERVICE_CREATE_RDB_TABLE, RDB_SERVICE_DESTROY_RDB_TABLE, - RDB_SERVICE_CMD_OPEN_STORE, + RDB_SERVICE_CMD_GET_SCHEMA, RDB_SERVICE_CMD_MAX }; virtual std::string ObtainDistributedTableName(const std::string &device, const std::string &table) = 0; @@ -62,9 +62,9 @@ public: virtual int32_t InitNotifier(const std::string& bundleName, const sptr notifier) = 0; - /*Cloud Data*/ - virtual int32_t OpenStore(const CloudParam &cloudParam) = 0; + virtual int32_t GetSchema(const std::string &bundleName, const std::string &storeName) = 0; + static constexpr const char *SERVICE_NAME = "relational_store"; protected: virtual int32_t DoSync(const RdbSyncerParam ¶m, const SyncOption &option, const RdbPredicates &predicates, SyncResult &result) = 0; diff --git a/relational_store/interfaces/inner_api/rdb/include/rdb_store_config.h b/relational_store/interfaces/inner_api/rdb/include/rdb_store_config.h index 6bcc799c..ad3c98bf 100644 --- a/relational_store/interfaces/inner_api/rdb/include/rdb_store_config.h +++ b/relational_store/interfaces/inner_api/rdb/include/rdb_store_config.h @@ -426,27 +426,6 @@ public: * @brief Obtains the encrypt key in this {@code StoreConfig} object. */ std::vector GetEncryptKey() const; - - /** - * @brief Sets the version for the object. - */ - void SetVersion(int32_t version); - - /** - * @brief Obtains the version in this {@code StoreConfig} object. - */ - int32_t GetVersion() const; - - /** - * @brief Sets the cloudId for the object. - */ - void SetCloudId(std::string cloudId); - - /** - * @brief Obtains the cloudId in this {@code StoreConfig} object. - */ - std::string GetCloudId() const; - private: void ClearEncryptKey(); @@ -481,7 +460,7 @@ private: //cloud rdb std::string cloudId_; - int32_t schemaVerion_ = -1; +// int32_t schemaVerion_ = -1; }; } // namespace OHOS::NativeRdb diff --git a/relational_store/interfaces/inner_api/rdb/include/rdb_types.h b/relational_store/interfaces/inner_api/rdb/include/rdb_types.h index 14934409..19c7f8a8 100644 --- a/relational_store/interfaces/inner_api/rdb/include/rdb_types.h +++ b/relational_store/interfaces/inner_api/rdb/include/rdb_types.h @@ -52,7 +52,7 @@ struct CloudParam { std::string bundleName; std::string storeName; std::string cloudId; - int32_t schemaVerion; +// int32_t schemaVerion; }; enum SyncMode { diff --git a/relational_store/interfaces/inner_api/rdb/include/values_bucket.h b/relational_store/interfaces/inner_api/rdb/include/values_bucket.h index 261f7693..c064fa09 100644 --- a/relational_store/interfaces/inner_api/rdb/include/values_bucket.h +++ b/relational_store/interfaces/inner_api/rdb/include/values_bucket.h @@ -147,7 +147,7 @@ public: * @brief Obtains the ValuesBucket object's valuesmap. */ RDB_API_EXPORT std::map GetAll() const; - + std::map values_; }; diff --git a/relational_store/relational_store.gni b/relational_store/relational_store.gni index b886073a..442ce6d8 100644 --- a/relational_store/relational_store.gni +++ b/relational_store/relational_store.gni @@ -26,3 +26,5 @@ relational_store_native_path = "${relational_store_base_path}/frameworks/native" relational_store_innerapi_path = "${relational_store_base_path}/interfaces/inner_api" + +cloud_data_native_path = "${relational_store_base_path}/frameworks/native/cloud_data" \ No newline at end of file diff --git a/test/include/CMakeLists.txt b/test/include/CMakeLists.txt index c46a8d0f..3b964f9c 100644 --- a/test/include/CMakeLists.txt +++ b/test/include/CMakeLists.txt @@ -40,6 +40,7 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../relational_store/interfaces/i include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../relational_store/interfaces/inner_api/dataability/include) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../relational_store/interfaces/inner_api/rdb/include) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../relational_store/interfaces/inner_api/rdb_data_share_adapter/include) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../relational_store/interfaces/inner_api/rdb_device_manager_adapter/include) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../relational_store/frameworks/native/rdb_data_share_adapter/include) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../data_share/interfaces/inner_api/common/include) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../data_share/interfaces/inner_api/consumer/include) -- Gitee From fa0e34ab1eed5f9fb1b2ea7e3bd726fb24792edb Mon Sep 17 00:00:00 2001 From: htt1997 Date: Mon, 24 Apr 2023 16:21:09 +0800 Subject: [PATCH 32/44] fix:add anonymous Signed-off-by: htt1997 --- .../service/object/object_service_stub.cpp | 16 ++++++++++------ .../service/rdb/rdb_service_stub.cpp | 3 ++- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/datamgr_service/services/distributeddataservice/service/object/object_service_stub.cpp b/datamgr_service/services/distributeddataservice/service/object/object_service_stub.cpp index a7118b31..9a5281bf 100644 --- a/datamgr_service/services/distributeddataservice/service/object/object_service_stub.cpp +++ b/datamgr_service/services/distributeddataservice/service/object/object_service_stub.cpp @@ -34,8 +34,8 @@ int32_t ObjectServiceStub::ObjectStoreSaveOnRemote(MessageParcel &data, MessageP sptr obj; if (!ITypesUtil::Unmarshal(data, bundleName, sessionId, deviceId, objectData, obj)) { ZLOGE("Unmarshal sessionId:%{public}s bundleName:%{public}s deviceId:%{public}s objectData size:%{public}zu", - sessionId.c_str(), bundleName.c_str(), DistributedData::Anonymous::Change(deviceId).c_str(), - objectData.size()); + DistributedData::Anonymous::Change(sessionId).c_str(), bundleName.c_str(), + DistributedData::Anonymous::Change(deviceId).c_str(), objectData.size()); return IPC_STUB_INVALID_DATA_ERR; } if (obj == nullptr) { @@ -56,7 +56,8 @@ int32_t ObjectServiceStub::ObjectStoreRevokeSaveOnRemote(MessageParcel &data, Me std::string bundleName; sptr obj; if (!ITypesUtil::Unmarshal(data, bundleName, sessionId, obj)) { - ZLOGE("Unmarshal sessionId:%{public}s bundleName:%{public}s", sessionId.c_str(), bundleName.c_str()); + ZLOGE("Unmarshal sessionId:%{public}s bundleName:%{public}s", + DistributedData::Anonymous::Change(sessionId).c_str(), bundleName.c_str()); return IPC_STUB_INVALID_DATA_ERR; } if (obj == nullptr) { @@ -77,7 +78,8 @@ int32_t ObjectServiceStub::ObjectStoreRetrieveOnRemote(MessageParcel &data, Mess std::string bundleName; sptr obj; if (!ITypesUtil::Unmarshal(data, bundleName, sessionId, obj)) { - ZLOGE("Unmarshal sessionId:%{public}s bundleName:%{public}s", sessionId.c_str(), bundleName.c_str()); + ZLOGE("Unmarshal sessionId:%{public}s bundleName:%{public}s", + DistributedData::Anonymous::Change(sessionId).c_str(), bundleName.c_str()); return IPC_STUB_INVALID_DATA_ERR; } if (obj == nullptr) { @@ -98,7 +100,8 @@ int32_t ObjectServiceStub::OnSubscribeRequest(MessageParcel &data, MessageParcel std::string bundleName; sptr obj; if (!ITypesUtil::Unmarshal(data, bundleName, sessionId, obj)) { - ZLOGE("Unmarshal sessionId:%{public}s bundleName:%{public}s", sessionId.c_str(), bundleName.c_str()); + ZLOGE("Unmarshal sessionId:%{public}s bundleName:%{public}s", + DistributedData::Anonymous::Change(sessionId).c_str(), bundleName.c_str()); return IPC_STUB_INVALID_DATA_ERR; } if (obj == nullptr) { @@ -118,7 +121,8 @@ int32_t ObjectServiceStub::OnUnsubscribeRequest(MessageParcel &data, MessageParc std::string sessionId; std::string bundleName; if (!ITypesUtil::Unmarshal(data, bundleName, sessionId)) { - ZLOGE("Unmarshal sessionId:%{public}s bundleName:%{public}s", sessionId.c_str(), bundleName.c_str()); + ZLOGE("Unmarshal sessionId:%{public}s bundleName:%{public}s", + DistributedData::Anonymous::Change(sessionId).c_str(), bundleName.c_str()); return IPC_STUB_INVALID_DATA_ERR; } int32_t status = UnregisterDataChangeObserver(bundleName, sessionId); diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_stub.cpp b/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_stub.cpp index 32fed04b..85e3719e 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_stub.cpp +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_stub.cpp @@ -27,7 +27,8 @@ int32_t RdbServiceStub::OnRemoteObtainDistributedTableName(MessageParcel &data, std::string device; std::string table; if (!ITypesUtil::Unmarshal(data, device, table)) { - ZLOGE("Unmarshal device:%{public}s table:%{public}s", device.c_str(), table.c_str()); + ZLOGE("Unmarshal device:%{public}s table:%{public}s", DistributedData::Anonymous::Change(device).c_str(), + table.c_str()); return IPC_STUB_INVALID_DATA_ERR; } -- Gitee From f7fc667603012ba4e631dd600b5340d1879d6002 Mon Sep 17 00:00:00 2001 From: Sven Wang Date: Mon, 24 Apr 2023 20:05:42 +0800 Subject: [PATCH 33/44] update Signed-off-by: Sven Wang --- .../include/datashare_block_writer_impl.h | 8 +- .../include/datashare_shared_result_set.h | 6 +- .../{shared_block.h => shared_blocker.h} | 41 +++---- .../src/datashare_block_writer_impl.cpp | 4 +- .../common/src/datashare_result_set.cpp | 64 +++++------ .../{shared_block.cpp => shared_blocker.cpp} | 107 +++++++++--------- .../consumer/include/datashare_result_set.h | 10 +- .../service/CMakeLists.txt | 1 + .../include/abs_shared_result_set.h | 2 + .../native/appdatafwk/src/shared_block.cpp | 10 ++ .../native/rdb/include/sqlite_statement.h | 4 + .../native/rdb/include/step_result_set.h | 5 + .../native/rdb/src/abs_result_set.cpp | 10 ++ .../native/rdb/src/abs_shared_result_set.cpp | 29 +++++ .../frameworks/native/rdb/src/asset_value.cpp | 16 --- .../native/rdb/src/sqlite_statement.cpp | 62 ++++++++++ .../native/rdb/src/step_result_set.cpp | 45 ++++++++ .../native/rdb/src/value_object.cpp | 17 +++ .../appdatafwk/include/shared_block.h | 14 +++ .../js/@ohos.data.relationalStore.d.ts | 10 +- .../inner_api/rdb/include/abs_result_set.h | 33 ++++++ .../rdb/include/abs_shared_result_set.h | 23 ++++ .../inner_api/rdb/include/asset_value.h | 4 + .../inner_api/rdb/include/result_set.h | 6 +- .../inner_api/rdb/include/value_object.h | 39 ++++++- 25 files changed, 432 insertions(+), 138 deletions(-) rename data_share/frameworks/native/common/include/{shared_block.h => shared_blocker.h} (92%) rename data_share/frameworks/native/common/src/{shared_block.cpp => shared_blocker.cpp} (76%) delete mode 100644 relational_store/frameworks/native/rdb/src/asset_value.cpp diff --git a/data_share/frameworks/native/common/include/datashare_block_writer_impl.h b/data_share/frameworks/native/common/include/datashare_block_writer_impl.h index 97b70c8f..74c53a5d 100644 --- a/data_share/frameworks/native/common/include/datashare_block_writer_impl.h +++ b/data_share/frameworks/native/common/include/datashare_block_writer_impl.h @@ -16,7 +16,7 @@ #ifndef DATASHARE_BLOCK_WRITER_IMPL_H #define DATASHARE_BLOCK_WRITER_IMPL_H -#include "shared_block.h" +#include "shared_blocker.h" #include "result_set_bridge.h" #include "datashare_errno.h" @@ -76,7 +76,7 @@ public: /** * Get Block */ - AppDataFwk::SharedBlock *GetBlock() const; + SharedBlock *GetBlock() const; private: /** @@ -89,11 +89,11 @@ private: */ int ConvertErrorCode(int shareBlockErr) { - return shareBlockErr == AppDataFwk::SharedBlock::SHARED_BLOCK_OK ? E_OK : E_ERROR; + return shareBlockErr == SharedBlock::SHARED_BLOCK_OK ? E_OK : E_ERROR; } private: - AppDataFwk::SharedBlock *shareBlock_; + SharedBlock *shareBlock_; }; } // namespace DataShare } // namespace OHOS diff --git a/data_share/frameworks/native/common/include/datashare_shared_result_set.h b/data_share/frameworks/native/common/include/datashare_shared_result_set.h index c8a5fc6f..8bb7c75f 100644 --- a/data_share/frameworks/native/common/include/datashare_shared_result_set.h +++ b/data_share/frameworks/native/common/include/datashare_shared_result_set.h @@ -17,7 +17,7 @@ #define DATASHARE_SHARED_RESULT_SET_H #include -#include "shared_block.h" +#include "shared_blocker.h" namespace OHOS { namespace DataShare { @@ -28,11 +28,11 @@ public: /** * Obtains a block from the {@link SharedResultSet} */ - virtual AppDataFwk::SharedBlock *GetBlock() const = 0; + virtual SharedBlock *GetBlock() const = 0; /** * Adds the data of a {@code SharedResultSet} to a {@link SharedBlock} */ - virtual void FillBlock(int startRowIndex, AppDataFwk::SharedBlock *block) = 0; + virtual void FillBlock(int startRowIndex, SharedBlock *block) = 0; /** * Called when the position of the result set changes */ diff --git a/data_share/frameworks/native/common/include/shared_block.h b/data_share/frameworks/native/common/include/shared_blocker.h similarity index 92% rename from data_share/frameworks/native/common/include/shared_block.h rename to data_share/frameworks/native/common/include/shared_blocker.h index 1230171c..f6980c83 100644 --- a/data_share/frameworks/native/common/include/shared_block.h +++ b/data_share/frameworks/native/common/include/shared_blocker.h @@ -13,28 +13,29 @@ * limitations under the License. */ -#ifndef SHARED_BLOCK_H -#define SHARED_BLOCK_H +#ifndef SHARED_BLOCKER_H +#define SHARED_BLOCKER_H +#include #include - #include -#include + #include "message_parcel.h" #include "parcel.h" #include "securec.h" namespace OHOS { -namespace AppDataFwk { +namespace DataShare { static const uint32_t INVALID_ROW_RECORD = 0xFFFFFFFF; /** * This class stores a set of rows from a database in a buffer, * which is used as the set of query result. */ -class SharedBlock { +class SharedBlocker { public: /* Cell Unit types. */ - enum { + enum + { CELL_UNIT_TYPE_NULL = 0, CELL_UNIT_TYPE_INTEGER = 1, CELL_UNIT_TYPE_FLOAT = 2, @@ -43,7 +44,8 @@ public: }; /* SharedBlock error types. */ - enum { + enum + { SHARED_BLOCK_OK = 0, SHARED_BLOCK_BAD_VALUE = 1, SHARED_BLOCK_NO_MEMORY = 2, @@ -68,12 +70,12 @@ public: /** * SharedBlock constructor. */ - SharedBlock(const std::string &name, sptr ashmem, size_t size, bool readOnly); + SharedBlocker(const std::string &name, sptr ashmem, size_t size, bool readOnly); /** * SharedBlock constructor. */ - ~SharedBlock(); + ~SharedBlocker(); /** * Init current shared block. @@ -83,7 +85,7 @@ public: /** * Create a shared block. */ - static int Create(const std::string &name, size_t size, SharedBlock *&outSharedBlock); + static int Create(const std::string &name, size_t size, SharedBlocker *&outSharedBlock); /** * Clear current shared block. @@ -204,7 +206,7 @@ public: int WriteMessageParcel(MessageParcel &parcel); - static int ReadMessageParcel(MessageParcel &parcel, SharedBlock *&block); + static int ReadMessageParcel(MessageParcel &parcel, SharedBlocker *&block); /** * Write raw data in block. */ @@ -263,7 +265,7 @@ private: */ static const size_t COL_MAX_NUM = 32767; - struct SharedBlockHeader { + struct BlockerHeader { /* Offset of the lowest unused byte in the block. */ uint32_t unusedOffset; /* Offset of the first row group. */ @@ -285,7 +287,7 @@ private: uint32_t nextGroupOffset; }; - SharedBlockHeader *mHeader; + BlockerHeader *mHeader; /** * Allocate a portion of the block. Returns the offset of the allocation. @@ -300,7 +302,7 @@ private: int PutBlobOrString(uint32_t row, uint32_t column, const void *value, size_t size, int32_t type); static int CreateSharedBlock(const std::string &name, size_t size, sptr ashmem, - SharedBlock *&outSharedBlock); + SharedBlocker *&outSharedBlock); uint32_t OffsetFromPtr(void *ptr); @@ -318,13 +320,14 @@ private: /** * Convert utf8 string to utf16. */ - static std::u16string ToUtf16(const std::string& str); + static std::u16string ToUtf16(const std::string &str); /** * Convert utf16 string to utf8. */ - static std::string ToUtf8(const std::u16string& str16); + static std::string ToUtf8(const std::u16string &str16); }; -} // namespace AppDataFwk +using SharedBlock = SharedBlocker; +} // namespace DataShare } // namespace OHOS -#endif +#endif // SHARED_BLOCKER_H diff --git a/data_share/frameworks/native/common/src/datashare_block_writer_impl.cpp b/data_share/frameworks/native/common/src/datashare_block_writer_impl.cpp index 8442cc02..33070de5 100644 --- a/data_share/frameworks/native/common/src/datashare_block_writer_impl.cpp +++ b/data_share/frameworks/native/common/src/datashare_block_writer_impl.cpp @@ -25,7 +25,7 @@ DataShareBlockWriterImpl::DataShareBlockWriterImpl() : shareBlock_(nullptr) DataShareBlockWriterImpl::DataShareBlockWriterImpl(const std::string &name, size_t size) : shareBlock_(nullptr) { - AppDataFwk::SharedBlock::Create(name, size, shareBlock_); + SharedBlock::Create(name, size, shareBlock_); } DataShareBlockWriterImpl::~DataShareBlockWriterImpl() @@ -91,7 +91,7 @@ int DataShareBlockWriterImpl::Write(uint32_t column, const char *value, size_t s return ConvertErrorCode(shareBlock_->PutString(currentRowIndex, column, value, sizeIncludingNull)); } -AppDataFwk::SharedBlock *DataShareBlockWriterImpl::GetBlock() const +SharedBlock *DataShareBlockWriterImpl::GetBlock() const { return shareBlock_; } diff --git a/data_share/frameworks/native/common/src/datashare_result_set.cpp b/data_share/frameworks/native/common/src/datashare_result_set.cpp index 271671ec..742c0291 100644 --- a/data_share/frameworks/native/common/src/datashare_result_set.cpp +++ b/data_share/frameworks/native/common/src/datashare_result_set.cpp @@ -94,7 +94,7 @@ bool DataShareResultSet::OnGo(int startRowIndex, int targetRowIndex, int *cached return true; } -void DataShareResultSet::FillBlock(int startRowIndex, AppDataFwk::SharedBlock *block) +void DataShareResultSet::FillBlock(int startRowIndex, SharedBlock *block) { return; } @@ -102,7 +102,7 @@ void DataShareResultSet::FillBlock(int startRowIndex, AppDataFwk::SharedBlock *b /** * Get current shared block */ -AppDataFwk::SharedBlock *DataShareResultSet::GetBlock() const +SharedBlock *DataShareResultSet::GetBlock() const { return sharedBlock_; } @@ -111,7 +111,7 @@ int DataShareResultSet::GetDataType(int columnIndex, DataType &dataType) { int rowCount = 0; GetRowCount(rowCount); - AppDataFwk::SharedBlock::CellUnit *cellUnit = + SharedBlock::CellUnit *cellUnit = sharedBlock_->GetCellUnit(static_cast(rowPos_) - startRowPos_, static_cast(columnIndex)); if (!cellUnit) { LOG_ERROR("cellUnit is null!"); @@ -168,7 +168,7 @@ int DataShareResultSet::GetBlob(int columnIndex, std::vector &value) return errorCode; } - AppDataFwk::SharedBlock::CellUnit *cellUnit = sharedBlock_->GetCellUnit(rowPos_ - startRowPos_, columnIndex); + SharedBlock::CellUnit *cellUnit = sharedBlock_->GetCellUnit(rowPos_ - startRowPos_, columnIndex); if (!cellUnit) { LOG_ERROR("cellUnit is null!"); return E_ERROR; @@ -176,8 +176,8 @@ int DataShareResultSet::GetBlob(int columnIndex, std::vector &value) value.resize(0); int type = cellUnit->type; - if (type == AppDataFwk::SharedBlock::CELL_UNIT_TYPE_BLOB - || type == AppDataFwk::SharedBlock::CELL_UNIT_TYPE_STRING) { + if (type == SharedBlock::CELL_UNIT_TYPE_BLOB + || type == SharedBlock::CELL_UNIT_TYPE_STRING) { size_t size; const auto *blob = static_cast(sharedBlock_->GetCellUnitValueBlob(cellUnit, &size)); if (size == 0 || blob == nullptr) { @@ -187,11 +187,11 @@ int DataShareResultSet::GetBlob(int columnIndex, std::vector &value) value.assign(blob, blob + size); } return E_OK; - } else if (type == AppDataFwk::SharedBlock::CELL_UNIT_TYPE_INTEGER) { + } else if (type == SharedBlock::CELL_UNIT_TYPE_INTEGER) { return E_OK; - } else if (type == AppDataFwk::SharedBlock::CELL_UNIT_TYPE_NULL) { + } else if (type == SharedBlock::CELL_UNIT_TYPE_NULL) { return E_OK; - } else if (type == AppDataFwk::SharedBlock::CELL_UNIT_TYPE_FLOAT) { + } else if (type == SharedBlock::CELL_UNIT_TYPE_FLOAT) { return E_OK; } else { LOG_ERROR("AppDataFwk::SharedBlock::nothing !"); @@ -205,30 +205,30 @@ int DataShareResultSet::GetString(int columnIndex, std::string &value) LOG_ERROR("sharedBlock is null!"); return E_ERROR; } - AppDataFwk::SharedBlock::CellUnit *cellUnit = sharedBlock_->GetCellUnit(rowPos_ - startRowPos_, columnIndex); + SharedBlock::CellUnit *cellUnit = sharedBlock_->GetCellUnit(rowPos_ - startRowPos_, columnIndex); if (!cellUnit) { LOG_ERROR("cellUnit is null!"); return E_ERROR; } int type = cellUnit->type; - if (type == AppDataFwk::SharedBlock::CELL_UNIT_TYPE_STRING) { + if (type == SharedBlock::CELL_UNIT_TYPE_STRING) { size_t sizeIncludingNull; value = std::string(sharedBlock_->GetCellUnitValueString(cellUnit, &sizeIncludingNull)); return E_OK; - } else if (type == AppDataFwk::SharedBlock::CELL_UNIT_TYPE_NULL) { + } else if (type == SharedBlock::CELL_UNIT_TYPE_NULL) { return E_ERROR; - } else if (type == AppDataFwk::SharedBlock::CELL_UNIT_TYPE_INTEGER) { + } else if (type == SharedBlock::CELL_UNIT_TYPE_INTEGER) { int64_t tempValue = cellUnit->cell.longValue; value = std::to_string(tempValue); return E_OK; - } else if (type == AppDataFwk::SharedBlock::CELL_UNIT_TYPE_FLOAT) { + } else if (type == SharedBlock::CELL_UNIT_TYPE_FLOAT) { double tempValue = cellUnit->cell.doubleValue; std::ostringstream os; if (os << tempValue) { value = os.str(); } return E_OK; - } else if (type == AppDataFwk::SharedBlock::CELL_UNIT_TYPE_BLOB) { + } else if (type == SharedBlock::CELL_UNIT_TYPE_BLOB) { return E_ERROR; } else { LOG_ERROR("GetString is failed!"); @@ -242,7 +242,7 @@ int DataShareResultSet::GetInt(int columnIndex, int &value) LOG_ERROR("sharedBlock is null!"); return E_ERROR; } - AppDataFwk::SharedBlock::CellUnit *cellUnit = sharedBlock_->GetCellUnit(rowPos_ - startRowPos_, columnIndex); + SharedBlock::CellUnit *cellUnit = sharedBlock_->GetCellUnit(rowPos_ - startRowPos_, columnIndex); if (!cellUnit) { LOG_ERROR("cellUnit is null!"); return E_ERROR; @@ -257,7 +257,7 @@ int DataShareResultSet::GetLong(int columnIndex, int64_t &value) LOG_ERROR("sharedBlock is null!"); return E_ERROR; } - AppDataFwk::SharedBlock::CellUnit *cellUnit = sharedBlock_->GetCellUnit(rowPos_ - startRowPos_, columnIndex); + SharedBlock::CellUnit *cellUnit = sharedBlock_->GetCellUnit(rowPos_ - startRowPos_, columnIndex); if (!cellUnit) { LOG_ERROR("cellUnit is null!"); return E_ERROR; @@ -265,21 +265,21 @@ int DataShareResultSet::GetLong(int columnIndex, int64_t &value) int type = cellUnit->type; - if (type == AppDataFwk::SharedBlock::CELL_UNIT_TYPE_INTEGER) { + if (type == SharedBlock::CELL_UNIT_TYPE_INTEGER) { value = cellUnit->cell.longValue; return E_OK; - } else if (type == AppDataFwk::SharedBlock::CELL_UNIT_TYPE_STRING) { + } else if (type == SharedBlock::CELL_UNIT_TYPE_STRING) { size_t sizeIncludingNull; const char *tempValue = sharedBlock_->GetCellUnitValueString(cellUnit, &sizeIncludingNull); value = ((sizeIncludingNull > 1) && (tempValue != nullptr)) ? long(strtoll(tempValue, nullptr, 0)) : 0L; return E_OK; - } else if (type == AppDataFwk::SharedBlock::CELL_UNIT_TYPE_FLOAT) { + } else if (type == SharedBlock::CELL_UNIT_TYPE_FLOAT) { value = (int64_t)cellUnit->cell.doubleValue; return E_OK; - } else if (type == AppDataFwk::SharedBlock::CELL_UNIT_TYPE_NULL) { + } else if (type == SharedBlock::CELL_UNIT_TYPE_NULL) { value = 0L; return E_OK; - } else if (type == AppDataFwk::SharedBlock::CELL_UNIT_TYPE_BLOB) { + } else if (type == SharedBlock::CELL_UNIT_TYPE_BLOB) { value = 0L; return E_OK; } else { @@ -294,27 +294,27 @@ int DataShareResultSet::GetDouble(int columnIndex, double &value) if (errorCode != E_OK) { return errorCode; } - AppDataFwk::SharedBlock::CellUnit *cellUnit = sharedBlock_->GetCellUnit(rowPos_ - startRowPos_, columnIndex); + SharedBlock::CellUnit *cellUnit = sharedBlock_->GetCellUnit(rowPos_ - startRowPos_, columnIndex); if (!cellUnit) { LOG_ERROR("cellUnit is null!"); return E_ERROR; } int type = cellUnit->type; - if (type == AppDataFwk::SharedBlock::CELL_UNIT_TYPE_FLOAT) { + if (type == SharedBlock::CELL_UNIT_TYPE_FLOAT) { value = cellUnit->cell.doubleValue; return E_OK; - } else if (type == AppDataFwk::SharedBlock::CELL_UNIT_TYPE_STRING) { + } else if (type == SharedBlock::CELL_UNIT_TYPE_STRING) { size_t sizeIncludingNull; const char *tempValue = sharedBlock_->GetCellUnitValueString(cellUnit, &sizeIncludingNull); value = ((sizeIncludingNull > 1) && (tempValue != nullptr)) ? strtod(tempValue, nullptr) : 0.0; return E_OK; - } else if (type == AppDataFwk::SharedBlock::CELL_UNIT_TYPE_INTEGER) { + } else if (type == SharedBlock::CELL_UNIT_TYPE_INTEGER) { value = static_cast(cellUnit->cell.longValue); return E_OK; - } else if (type == AppDataFwk::SharedBlock::CELL_UNIT_TYPE_NULL) { + } else if (type == SharedBlock::CELL_UNIT_TYPE_NULL) { value = 0.0; return E_OK; - } else if (type == AppDataFwk::SharedBlock::CELL_UNIT_TYPE_BLOB) { + } else if (type == SharedBlock::CELL_UNIT_TYPE_BLOB) { value = 0.0; return E_OK; } else { @@ -330,12 +330,12 @@ int DataShareResultSet::IsColumnNull(int columnIndex, bool &isNull) if (errorCode != E_OK) { return errorCode; } - AppDataFwk::SharedBlock::CellUnit *cellUnit = sharedBlock_->GetCellUnit(rowPos_ - startRowPos_, columnIndex); + SharedBlock::CellUnit *cellUnit = sharedBlock_->GetCellUnit(rowPos_ - startRowPos_, columnIndex); if (!cellUnit) { LOG_ERROR("cellUnit is null!"); return E_ERROR; } - if (cellUnit->type == AppDataFwk::SharedBlock::CELL_UNIT_TYPE_NULL) { + if (cellUnit->type == SharedBlock::CELL_UNIT_TYPE_NULL) { isNull = true; return E_OK; } @@ -355,7 +355,7 @@ int DataShareResultSet::Close() /** * Allocates a new shared block to an {@link DataShareResultSet} */ -void DataShareResultSet::SetBlock(AppDataFwk::SharedBlock *block) +void DataShareResultSet::SetBlock(SharedBlock *block) { if (sharedBlock_ != block) { ClosedBlock(); @@ -421,7 +421,7 @@ bool DataShareResultSet::Unmarshalling(MessageParcel &parcel) if (sharedBlock_ != nullptr) { return false; } - int result = AppDataFwk::SharedBlock::ReadMessageParcel(parcel, sharedBlock_); + int result = SharedBlock::ReadMessageParcel(parcel, sharedBlock_); if (result < 0) { LOG_ERROR("create from parcel error is %{public}d.", result); } diff --git a/data_share/frameworks/native/common/src/shared_block.cpp b/data_share/frameworks/native/common/src/shared_blocker.cpp similarity index 76% rename from data_share/frameworks/native/common/src/shared_block.cpp rename to data_share/frameworks/native/common/src/shared_blocker.cpp index 49380206..a4050996 100644 --- a/data_share/frameworks/native/common/src/shared_block.cpp +++ b/data_share/frameworks/native/common/src/shared_blocker.cpp @@ -12,7 +12,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#include "shared_block.h" +#include "shared_blocker.h" #include #include #include @@ -26,93 +26,96 @@ #include "datashare_log.h" namespace OHOS { -namespace AppDataFwk { -using namespace OHOS::DataShare; -SharedBlock::SharedBlock(const std::string &name, sptr ashmem, size_t size, bool readOnly) +namespace DataShare { +SharedBlocker::SharedBlocker(const std::string &name, sptr ashmem, size_t size, bool readOnly) : mName(name), ashmem_(ashmem), mSize(size), mReadOnly(readOnly), mHeader(nullptr) { } -SharedBlock::~SharedBlock() +SharedBlocker::~SharedBlocker() { if (ashmem_ != nullptr) { ashmem_->UnmapAshmem(); ashmem_->CloseAshmem(); +<<<<<<< HEAD:data_share/frameworks/native/common/src/shared_blocker.cpp + LOG_WARN("SharedBlocker: close ashmem"); +======= LOG_DEBUG("SharedBlock: close ashmem"); +>>>>>>> fcccfeffd0b72b4f1eb7b880b16b8e2b3cec1364:data_share/frameworks/native/common/src/shared_block.cpp } } -std::u16string SharedBlock::ToUtf16(const std::string& str) +std::u16string SharedBlocker::ToUtf16(const std::string& str) { return OHOS::Str8ToStr16(str); } -std::string SharedBlock::ToUtf8(const std::u16string& str16) +std::string SharedBlocker::ToUtf8(const std::u16string& str16) { return OHOS::Str16ToStr8(str16); } -bool SharedBlock::Init() +bool SharedBlocker::Init() { - mData = const_cast(ashmem_->ReadFromAshmem(sizeof(SharedBlockHeader), 0)); - mHeader = static_cast(mData); + mData = const_cast(ashmem_->ReadFromAshmem(sizeof(BlockerHeader), 0)); + mHeader = static_cast(mData); if (mHeader == nullptr) { return false; } return true; } -int SharedBlock::CreateSharedBlock(const std::string &name, size_t size, sptr ashmem, - SharedBlock *&outSharedBlock) +int SharedBlocker::CreateSharedBlock(const std::string &name, size_t size, sptr ashmem, + SharedBlocker *&outSharedBlocker) { - outSharedBlock = new SharedBlock(name, ashmem, size, false); - if (outSharedBlock == nullptr) { - LOG_ERROR("CreateSharedBlock: new SharedBlock error."); + outSharedBlocker = new SharedBlocker(name, ashmem, size, false); + if (outSharedBlocker == nullptr) { + LOG_ERROR("CreateSharedBlocker: new SharedBlocker error."); return SHARED_BLOCK_BAD_VALUE; } - if (!outSharedBlock->Init()) { - delete outSharedBlock; - outSharedBlock = nullptr; - LOG_ERROR("CreateSharedBlock: mHeader is null."); + if (!outSharedBlocker->Init()) { + delete outSharedBlocker; + outSharedBlocker = nullptr; + LOG_ERROR("CreateSharedBlocker: mHeader is null."); return SHARED_BLOCK_ASHMEM_ERROR; } return SHARED_BLOCK_OK; } -int SharedBlock::Create(const std::string &name, size_t size, SharedBlock *&outSharedBlock) +int SharedBlocker::Create(const std::string &name, size_t size, SharedBlocker *&outSharedBlocker) { - std::string ashmemName = "SharedBlock:" + name; + std::string ashmemName = "SharedBlocker:" + name; sptr ashmem = Ashmem::CreateAshmem(ashmemName.c_str(), size); if (ashmem == nullptr) { - LOG_ERROR("SharedBlock: CreateAshmem function error."); + LOG_ERROR("SharedBlocker: CreateAshmem function error."); return SHARED_BLOCK_ASHMEM_ERROR; } bool ret = ashmem->MapReadAndWriteAshmem(); if (!ret) { - LOG_ERROR("SharedBlock: MapReadAndWriteAshmem function error."); + LOG_ERROR("SharedBlocker: MapReadAndWriteAshmem function error."); ashmem->CloseAshmem(); return SHARED_BLOCK_SET_PORT_ERROR; } - int result = CreateSharedBlock(name, size, ashmem, outSharedBlock); + int result = CreateSharedBlock(name, size, ashmem, outSharedBlocker); if (result == SHARED_BLOCK_OK) { return SHARED_BLOCK_OK; } ashmem->UnmapAshmem(); ashmem->CloseAshmem(); - outSharedBlock = nullptr; + outSharedBlocker = nullptr; return result; } -int SharedBlock::WriteMessageParcel(MessageParcel &parcel) +int SharedBlocker::WriteMessageParcel(MessageParcel &parcel) { return parcel.WriteString16(ToUtf16(mName)) && parcel.WriteAshmem(ashmem_); } -int SharedBlock::ReadMessageParcel(MessageParcel &parcel, SharedBlock *&block) +int SharedBlocker::ReadMessageParcel(MessageParcel &parcel, SharedBlocker *&block) { std::string name = ToUtf8(parcel.ReadString16()); sptr ashmem = parcel.ReadAshmem(); @@ -126,9 +129,9 @@ int SharedBlock::ReadMessageParcel(MessageParcel &parcel, SharedBlock *&block) ashmem->CloseAshmem(); return SHARED_BLOCK_SET_PORT_ERROR; } - block = new (std::nothrow) SharedBlock(name, ashmem, ashmem->GetAshmemSize(), true); + block = new (std::nothrow) SharedBlocker(name, ashmem, ashmem->GetAshmemSize(), true); if (block == nullptr) { - LOG_ERROR("ReadMessageParcel new SharedBlock error."); + LOG_ERROR("ReadMessageParcel new SharedBlocker error."); return SHARED_BLOCK_BAD_VALUE; } if (!block->Init()) { @@ -138,7 +141,7 @@ int SharedBlock::ReadMessageParcel(MessageParcel &parcel, SharedBlock *&block) return SHARED_BLOCK_ASHMEM_ERROR; } - LOG_DEBUG("Created SharedBlock from parcel: unusedOffset=%{private}" PRIu32 ", " + LOG_DEBUG("Created SharedBlocker from parcel: unusedOffset=%{private}" PRIu32 ", " "rowNums=%{private}" PRIu32 ", columnNums=%{private}" PRIu32 ", mSize=%{private}d", block->mHeader->unusedOffset, block->mHeader->rowNums, block->mHeader->columnNums, static_cast(block->mSize)); @@ -146,14 +149,14 @@ int SharedBlock::ReadMessageParcel(MessageParcel &parcel, SharedBlock *&block) return SHARED_BLOCK_OK; } -int SharedBlock::Clear() +int SharedBlocker::Clear() { if (mReadOnly) { return SHARED_BLOCK_INVALID_OPERATION; } - mHeader->unusedOffset = sizeof(SharedBlockHeader) + sizeof(RowGroupHeader); - mHeader->firstRowGroupOffset = sizeof(SharedBlockHeader); + mHeader->unusedOffset = sizeof(BlockerHeader) + sizeof(RowGroupHeader); + mHeader->firstRowGroupOffset = sizeof(BlockerHeader); mHeader->rowNums = 0; mHeader->columnNums = 0; mHeader->startPos_ = 0; @@ -169,7 +172,7 @@ int SharedBlock::Clear() return SHARED_BLOCK_OK; } -int SharedBlock::SetColumnNum(uint32_t numColumns) +int SharedBlocker::SetColumnNum(uint32_t numColumns) { if (mReadOnly) { return SHARED_BLOCK_INVALID_OPERATION; @@ -188,7 +191,7 @@ int SharedBlock::SetColumnNum(uint32_t numColumns) return SHARED_BLOCK_OK; } -int SharedBlock::AllocRow() +int SharedBlocker::AllocRow() { if (mReadOnly) { return SHARED_BLOCK_INVALID_OPERATION; @@ -225,7 +228,7 @@ int SharedBlock::AllocRow() return SHARED_BLOCK_OK; } -int SharedBlock::FreeLastRow() +int SharedBlocker::FreeLastRow() { if (mReadOnly) { return SHARED_BLOCK_INVALID_OPERATION; @@ -238,7 +241,7 @@ int SharedBlock::FreeLastRow() return SHARED_BLOCK_OK; } -uint32_t SharedBlock::Alloc(size_t size, bool aligned) +uint32_t SharedBlocker::Alloc(size_t size, bool aligned) { /* Number of unused offsets in the header */ uint32_t offsetDigit = 3; @@ -247,7 +250,7 @@ uint32_t SharedBlock::Alloc(size_t size, bool aligned) uint32_t nextFreeOffset; if (offset + size > mSize) { - LOG_ERROR("SharedBlock is full: requested allocation %{public}zu bytes," + LOG_ERROR("SharedBlocker is full: requested allocation %{public}zu bytes," " free space %{public}zu bytes, block size %{public}zu bytes", size, mSize - mHeader->unusedOffset, mSize); return 0; @@ -257,7 +260,7 @@ uint32_t SharedBlock::Alloc(size_t size, bool aligned) return offset; } -inline uint32_t *SharedBlock::GetRowOffset(uint32_t row) +inline uint32_t *SharedBlocker::GetRowOffset(uint32_t row) { uint32_t rowPos = row; @@ -279,7 +282,7 @@ inline uint32_t *SharedBlock::GetRowOffset(uint32_t row) return &group->rowOffsets[rowPos]; } -uint32_t *SharedBlock::AllocRowOffset() +uint32_t *SharedBlocker::AllocRowOffset() { uint32_t rowPos = mHeader->rowNums; @@ -318,10 +321,10 @@ uint32_t *SharedBlock::AllocRowOffset() return &group->rowOffsets[rowPos]; } -SharedBlock::CellUnit *SharedBlock::GetCellUnit(uint32_t row, uint32_t column) +SharedBlocker::CellUnit *SharedBlocker::GetCellUnit(uint32_t row, uint32_t column) { if (row >= mHeader->rowNums || column >= mHeader->columnNums) { - LOG_ERROR("Failed to read row %{public}" PRIu32 ", column %{public}" PRIu32 " from a SharedBlock" + LOG_ERROR("Failed to read row %{public}" PRIu32 ", column %{public}" PRIu32 " from a SharedBlocker" " which has %{public}" PRIu32 " rows, %{public}" PRIu32 " columns.", row, column, mHeader->rowNums, mHeader->columnNums); return nullptr; @@ -342,17 +345,17 @@ SharedBlock::CellUnit *SharedBlock::GetCellUnit(uint32_t row, uint32_t column) return &cellUnit[column]; } -int SharedBlock::PutBlob(uint32_t row, uint32_t column, const void *value, size_t size) +int SharedBlocker::PutBlob(uint32_t row, uint32_t column, const void *value, size_t size) { return PutBlobOrString(row, column, value, size, CELL_UNIT_TYPE_BLOB); } -int SharedBlock::PutString(uint32_t row, uint32_t column, const char *value, size_t sizeIncludingNull) +int SharedBlocker::PutString(uint32_t row, uint32_t column, const char *value, size_t sizeIncludingNull) { return PutBlobOrString(row, column, value, sizeIncludingNull, CELL_UNIT_TYPE_STRING); } -int SharedBlock::PutBlobOrString(uint32_t row, uint32_t column, const void *value, size_t size, int32_t type) +int SharedBlocker::PutBlobOrString(uint32_t row, uint32_t column, const void *value, size_t size, int32_t type) { if (mReadOnly) { return SHARED_BLOCK_INVALID_OPERATION; @@ -386,7 +389,7 @@ int SharedBlock::PutBlobOrString(uint32_t row, uint32_t column, const void *valu return SHARED_BLOCK_OK; } -int SharedBlock::PutLong(uint32_t row, uint32_t column, int64_t value) +int SharedBlocker::PutLong(uint32_t row, uint32_t column, int64_t value) { if (mReadOnly) { return SHARED_BLOCK_INVALID_OPERATION; @@ -402,7 +405,7 @@ int SharedBlock::PutLong(uint32_t row, uint32_t column, int64_t value) return SHARED_BLOCK_OK; } -int SharedBlock::PutDouble(uint32_t row, uint32_t column, double value) +int SharedBlocker::PutDouble(uint32_t row, uint32_t column, double value) { if (mReadOnly) { return SHARED_BLOCK_INVALID_OPERATION; @@ -418,7 +421,7 @@ int SharedBlock::PutDouble(uint32_t row, uint32_t column, double value) return SHARED_BLOCK_OK; } -int SharedBlock::PutNull(uint32_t row, uint32_t column) +int SharedBlocker::PutNull(uint32_t row, uint32_t column) { if (mReadOnly) { return SHARED_BLOCK_INVALID_OPERATION; @@ -435,14 +438,14 @@ int SharedBlock::PutNull(uint32_t row, uint32_t column) return SHARED_BLOCK_OK; } -size_t SharedBlock::SetRawData(const void *rawData, size_t size) +size_t SharedBlocker::SetRawData(const void *rawData, size_t size) { if (size <= 0) { - LOG_ERROR("SharedBlock rawData is less than or equal to 0M"); + LOG_ERROR("SharedBlocker rawData is less than or equal to 0M"); return SHARED_BLOCK_INVALID_OPERATION; } if (size > mSize) { - LOG_ERROR("SharedBlock size is %{public}zu, current byteArray size is %{public}zu", mSize, size); + LOG_ERROR("SharedBlocker size is %{public}zu, current byteArray size is %{public}zu", mSize, size); return SHARED_BLOCK_NO_MEMORY; } @@ -453,7 +456,7 @@ size_t SharedBlock::SetRawData(const void *rawData, size_t size) return SHARED_BLOCK_OK; } -uint32_t SharedBlock::OffsetFromPtr(void *ptr) +uint32_t SharedBlocker::OffsetFromPtr(void *ptr) { return static_cast(ptr) - static_cast(mData); } diff --git a/data_share/interfaces/inner_api/consumer/include/datashare_result_set.h b/data_share/interfaces/inner_api/consumer/include/datashare_result_set.h index 69a8adeb..f4b29e48 100644 --- a/data_share/interfaces/inner_api/consumer/include/datashare_result_set.h +++ b/data_share/interfaces/inner_api/consumer/include/datashare_result_set.h @@ -27,7 +27,7 @@ #include "message_parcel.h" #include "parcel.h" #include "result_set_bridge.h" -#include "shared_block.h" +#include "shared_blocker.h" namespace OHOS { namespace DataShare { @@ -135,7 +135,7 @@ public: /** * Obtains a block from the SharedResultSet. */ - AppDataFwk::SharedBlock *GetBlock() const override; + SharedBlock *GetBlock() const override; /** * Called when the position of the result set changes. @@ -145,12 +145,12 @@ public: /** * Adds the data of a SharedResultSet to a SharedBlock. */ - void FillBlock(int startRowIndex, AppDataFwk::SharedBlock *block) override; + void FillBlock(int startRowIndex, SharedBlock *block) override; /** * SetBlock. */ - virtual void SetBlock(AppDataFwk::SharedBlock *block); + virtual void SetBlock(SharedBlock *block); /** * Closes the result set, releasing all of its resources and making it completely invalid. @@ -179,7 +179,7 @@ private: // The actual position of the last row of data in the shareblock int endRowPos_ = -1; // The SharedBlock owned by this DataShareResultSet - AppDataFwk::SharedBlock *sharedBlock_ = nullptr; + SharedBlock *sharedBlock_ = nullptr; std::shared_ptr blockWriter_ = nullptr; std::shared_ptr bridge_ = nullptr; }; diff --git a/datamgr_service/services/distributeddataservice/service/CMakeLists.txt b/datamgr_service/services/distributeddataservice/service/CMakeLists.txt index 6c0f84ad..942ded11 100644 --- a/datamgr_service/services/distributeddataservice/service/CMakeLists.txt +++ b/datamgr_service/services/distributeddataservice/service/CMakeLists.txt @@ -47,6 +47,7 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../adapter/include/permission) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../adapter/include/security) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../adapter/include/utils) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../app/src) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../../../relational_store/interfaces/inner_api/appdatafwk/include) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../../../relational_store/interfaces/inner_api/cloud_data/include) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../../../relational_store/interfaces/inner_api/rdb/include) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../../../relational_store/interfaces/inner_api/rdb_data_share_adapter/include) diff --git a/mock/innerkits/native_appdatamgr/native_rdb/include/abs_shared_result_set.h b/mock/innerkits/native_appdatamgr/native_rdb/include/abs_shared_result_set.h index b5c67cc4..79dce00b 100644 --- a/mock/innerkits/native_appdatamgr/native_rdb/include/abs_shared_result_set.h +++ b/mock/innerkits/native_appdatamgr/native_rdb/include/abs_shared_result_set.h @@ -39,6 +39,8 @@ public: 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 IsColumnNull(int columnIndex, bool &isNull) override; int GetColumnType(int columnIndex, ColumnType &columnType) override; int GoToRow(int position) override; diff --git a/relational_store/frameworks/native/appdatafwk/src/shared_block.cpp b/relational_store/frameworks/native/appdatafwk/src/shared_block.cpp index 855c9e1c..4c56ccbf 100644 --- a/relational_store/frameworks/native/appdatafwk/src/shared_block.cpp +++ b/relational_store/frameworks/native/appdatafwk/src/shared_block.cpp @@ -349,6 +349,16 @@ int SharedBlock::PutString(uint32_t row, uint32_t column, const char *value, siz return PutBlobOrString(row, column, value, sizeIncludingNull, CELL_UNIT_TYPE_STRING); } +int SharedBlock::PutAsset(uint32_t row, uint32_t column, const void *value, size_t size) +{ + return PutBlobOrString(row, column, value, size, CELL_UNIT_TYPE_ASSET); +} + +int SharedBlock::PutAssets(uint32_t row, uint32_t column, const void *value, size_t size) +{ + return PutBlobOrString(row, column, value, size, CELL_UNIT_TYPE_ASSETS); +} + int SharedBlock::PutBlobOrString(uint32_t row, uint32_t column, const void *value, size_t size, int32_t type) { if (mReadOnly) { diff --git a/relational_store/frameworks/native/rdb/include/sqlite_statement.h b/relational_store/frameworks/native/rdb/include/sqlite_statement.h index ca4cb1d1..702f1cb6 100644 --- a/relational_store/frameworks/native/rdb/include/sqlite_statement.h +++ b/relational_store/frameworks/native/rdb/include/sqlite_statement.h @@ -40,6 +40,7 @@ public: int GetColumnString(int index, std::string &value) const; int GetColumnLong(int index, int64_t &value) const; int GetColumnDouble(int index, double &value) const; + int GetColumn(int index, ValueObject &value) const; bool IsReadOnly() const; int GetNumParameters(int &numParams) const; sqlite3_stmt *GetSql3Stmt() const @@ -48,6 +49,9 @@ public: } private: + using Asset = ValueObject::Asset; + using Assets = ValueObject::Assets; + int InnerBindArguments(const std::vector &bindArgs) const; std::string sql; sqlite3_stmt *stmtHandle; diff --git a/relational_store/frameworks/native/rdb/include/step_result_set.h b/relational_store/frameworks/native/rdb/include/step_result_set.h index 721405a2..7b7cd59c 100644 --- a/relational_store/frameworks/native/rdb/include/step_result_set.h +++ b/relational_store/frameworks/native/rdb/include/step_result_set.h @@ -47,6 +47,9 @@ public: 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 GetModifyTime(std::string &modifyTime) override; int IsColumnNull(int columnIndex, bool &isNull) override; bool IsClosed() const override; int Close() override; @@ -54,6 +57,8 @@ public: int PrepareStep(); private: + template + int GetValue(int32_t col, T &value); void Reset(); std::shared_ptr rdb; std::string sql; diff --git a/relational_store/frameworks/native/rdb/src/abs_result_set.cpp b/relational_store/frameworks/native/rdb/src/abs_result_set.cpp index 1a76944a..aba2d207 100644 --- a/relational_store/frameworks/native/rdb/src/abs_result_set.cpp +++ b/relational_store/frameworks/native/rdb/src/abs_result_set.cpp @@ -359,5 +359,15 @@ int AbsResultSet::GetModifyTime(std::string &modifyTime) { return E_NOT_SUPPORT; } + +int AbsResultSet::GetAsset(int32_t col, ValueObject::Asset &value) +{ + return E_NOT_SUPPORT; +} + +int AbsResultSet::GetAssets(int32_t col, ValueObject::Assets &value) +{ + return E_NOT_SUPPORT; +} } // namespace NativeRdb } // namespace OHOS \ No newline at end of file diff --git a/relational_store/frameworks/native/rdb/src/abs_shared_result_set.cpp b/relational_store/frameworks/native/rdb/src/abs_shared_result_set.cpp index b4d3c029..3d380e9b 100644 --- a/relational_store/frameworks/native/rdb/src/abs_shared_result_set.cpp +++ b/relational_store/frameworks/native/rdb/src/abs_shared_result_set.cpp @@ -319,6 +319,35 @@ int AbsSharedResultSet::GetDouble(int columnIndex, double &value) } } +int AbsSharedResultSet::GetAsset(int32_t col, ValueObject::Asset &value) +{ + DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__)); + int errorCode = CheckState(col); + if (errorCode != E_OK) { + return errorCode; + } + AppDataFwk::SharedBlock::CellUnit *cellUnit = sharedBlock_->GetCellUnit(sharedBlock_->GetBlockPos(), col); + if (!cellUnit) { + LOG_ERROR("AbsSharedResultSet::GetDouble cellUnit is null!"); + return E_ERROR; + } + int type = cellUnit->type; + if (type == AppDataFwk::SharedBlock::CELL_UNIT_TYPE_ASSET) { + size_t size = 0; + auto data = reinterpret_cast(sharedBlock_->GetCellUnitValueBlob(cellUnit, &size)); + ValueObject::Asset asset; + ValueObject::FromRawData(data, size, asset); + } else { + LOG_ERROR("AbsSharedResultSet::GetDouble AppDataFwk::SharedBlock::nothing !"); + return E_INVALID_OBJECT_TYPE; + } +} + +int AbsSharedResultSet::GetAssets(int32_t col, ValueObject::Assets &value) +{ + return AbsResultSet::GetAssets(col, value); +} + int AbsSharedResultSet::IsColumnNull(int columnIndex, bool &isNull) { int errorCode = CheckState(columnIndex); diff --git a/relational_store/frameworks/native/rdb/src/asset_value.cpp b/relational_store/frameworks/native/rdb/src/asset_value.cpp deleted file mode 100644 index 6b8c7ae5..00000000 --- a/relational_store/frameworks/native/rdb/src/asset_value.cpp +++ /dev/null @@ -1,16 +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. - */ - -#include "asset_value.h" \ No newline at end of file diff --git a/relational_store/frameworks/native/rdb/src/sqlite_statement.cpp b/relational_store/frameworks/native/rdb/src/sqlite_statement.cpp index 1f8e9a4f..a8dd2f52 100644 --- a/relational_store/frameworks/native/rdb/src/sqlite_statement.cpp +++ b/relational_store/frameworks/native/rdb/src/sqlite_statement.cpp @@ -392,6 +392,68 @@ int SqliteStatement::GetColumnDouble(int index, double &value) const return E_OK; } +int SqliteStatement::GetColumn(int index, ValueObject &value) const +{ + if (stmtHandle == nullptr) { + LOG_ERROR("invalid statement."); + return E_INVALID_STATEMENT; + } + + if (index >= columnCount) { + LOG_ERROR("index (%{public}d) >= columnCount (%{public}d)", index, columnCount); + return E_INVALID_COLUMN_INDEX; + } + + int type = sqlite3_column_type(stmtHandle, index); + switch (type) { + case SQLITE_FLOAT: + value = sqlite3_column_double(stmtHandle, index); + return E_OK; + case SQLITE_INTEGER: + value = static_cast(sqlite3_column_int64(stmtHandle, index)); + return E_OK; + case SQLITE_TEXT: + value = reinterpret_cast(sqlite3_column_text(stmtHandle, index)); + return E_OK; + case SQLITE_NULL: + return E_OK; + default: + break; + } + const char *decl = sqlite3_column_decltype(stmtHandle, index); + if (type != SQLITE_BLOB || decl == nullptr) { + LOG_ERROR("invalid type %{public}d.", type); + return E_ERROR; + } + int size = sqlite3_column_bytes(stmtHandle, index); + auto blob = static_cast(sqlite3_column_blob(stmtHandle, index)); + std::string declType = decl; + if (declType == ValueObject::DeclType()) { + Asset asset; + (void)ValueObject::FromRawData(blob, size, asset); + value = asset; + return E_OK; + } + if (declType == ValueObject::DeclType()) { + size_t offset = 0; + Assets assets; + while (offset < size) { + Asset asset; + offset += ValueObject::FromRawData(&blob[offset], size - offset, asset); + assets.push_back(std::move(asset)); + } + value = std::move(assets); + return E_OK; + } + std::vector rawData; + if (size > 0 || blob != nullptr) { + rawData.resize(size); + rawData.assign(blob, blob + size); + } + value = std::move(rawData); + return E_OK; +} + bool SqliteStatement::IsReadOnly() const { return readOnly; diff --git a/relational_store/frameworks/native/rdb/src/step_result_set.cpp b/relational_store/frameworks/native/rdb/src/step_result_set.cpp index 4308620f..cc41d6c6 100644 --- a/relational_store/frameworks/native/rdb/src/step_result_set.cpp +++ b/relational_store/frameworks/native/rdb/src/step_result_set.cpp @@ -402,6 +402,31 @@ int StepResultSet::GetDouble(int columnIndex, double &value) return E_OK; } +int StepResultSet::GetAsset(int32_t col, ValueObject::Asset &value) +{ + return GetValue(col, value); +} + +int StepResultSet::GetAssets(int32_t col, ValueObject::Assets &value) +{ + return GetValue(col, value); +} + +int StepResultSet::GetModifyTime(std::string &modifyTime) +{ + if (rowPos_ == INIT_POS) { + LOG_ERROR("query not executed."); + return E_STEP_RESULT_QUERY_NOT_EXECUTED; + } + auto index = std::find(columnNames_.begin(), columnNames_.end(), "modifyTime"); + int errCode = sqliteStatement->GetColumnString(index - columnNames_.begin(), modifyTime); + if (errCode != E_OK) { + LOG_ERROR("ret is %{public}d", errCode); + return errCode; + } + return E_OK; +} + int StepResultSet::IsColumnNull(int columnIndex, bool &isNull) { ColumnType columnType; @@ -421,5 +446,25 @@ bool StepResultSet::IsClosed() const { return isClosed; } + +template +int StepResultSet::GetValue(int32_t col, T &value) +{ + if (rowPos_ == INIT_POS) { + LOG_ERROR("query not executed."); + return E_STEP_RESULT_QUERY_NOT_EXECUTED; + } + ValueObject object; + int errCode = sqliteStatement->GetColumn(col, object); + if (errCode != E_OK) { + LOG_ERROR("ret is %{public}d", errCode); + return errCode; + } + if (object.value.index() != ValueObject::TYPE_INDEX) { + return E_INVALID_COLUMN_TYPE; + } + value = object; + return E_OK; +} } // namespace NativeRdb } // namespace OHOS diff --git a/relational_store/frameworks/native/rdb/src/value_object.cpp b/relational_store/frameworks/native/rdb/src/value_object.cpp index d288d127..e13203a2 100644 --- a/relational_store/frameworks/native/rdb/src/value_object.cpp +++ b/relational_store/frameworks/native/rdb/src/value_object.cpp @@ -15,6 +15,8 @@ #include "value_object.h" +#include + #include "rdb_errno.h" #include "sqlite_utils.h" @@ -160,5 +162,20 @@ int ValueObject::Get(T &output) const output = static_cast(*v); return E_OK; } + +std::vector ValueObject::ToRawData(Asset &asset) +{ + std::vector rawData; + uint32_t version = htole32(asset.version); + rawData.assign(reinterpret_cast(&version), reinterpret_cast(&version) + sizeof(version)); + return rawData; +} + +size_t ValueObject::FromRawData(const uint8_t *rawData, size_t length, Asset &asset) +{ + memcpy_s(&asset.version, sizeof(asset.version), rawData, length); + asset.version = le32toh(asset.version); + return sizeof(asset.version); +} } // namespace NativeRdb } // namespace OHOS diff --git a/relational_store/interfaces/inner_api/appdatafwk/include/shared_block.h b/relational_store/interfaces/inner_api/appdatafwk/include/shared_block.h index 46729315..766550eb 100644 --- a/relational_store/interfaces/inner_api/appdatafwk/include/shared_block.h +++ b/relational_store/interfaces/inner_api/appdatafwk/include/shared_block.h @@ -51,6 +51,10 @@ public: CELL_UNIT_TYPE_STRING = 3, /** Indicates the current Cell Unit data type is BLOB at the specified row and column.*/ CELL_UNIT_TYPE_BLOB = 4, + /** Indicates the current Cell Unit data type is Asset at the specified row and column.*/ + CELL_UNIT_TYPE_ASSET = 5, + /** Indicates the current Cell Unit data type is Assets at the specified row and column.*/ + CELL_UNIT_TYPE_ASSETS = 6, }; /** @@ -146,6 +150,16 @@ public: */ RDB_API_EXPORT int PutDouble(uint32_t row, uint32_t column, double value); + /** + * @brief Put Asset data to the shared block. + */ + RDB_API_EXPORT int PutAsset(uint32_t row, uint32_t column, const void *value, size_t size); + + /** + * @brief Put Assets data to the shared block. + */ + RDB_API_EXPORT int PutAssets(uint32_t row, uint32_t column, const void *value, size_t size); + /** * @brief Put Null data to the shared block. */ diff --git a/relational_store/interfaces/inner_api/js/@ohos.data.relationalStore.d.ts b/relational_store/interfaces/inner_api/js/@ohos.data.relationalStore.d.ts index 952af0af..67d3017f 100644 --- a/relational_store/interfaces/inner_api/js/@ohos.data.relationalStore.d.ts +++ b/relational_store/interfaces/inner_api/js/@ohos.data.relationalStore.d.ts @@ -295,7 +295,15 @@ declare namespace relationalStore { * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @since 9 */ - SUBSCRIBE_TYPE_REMOTE = 0 + SUBSCRIBE_TYPE_REMOTE = 0, + /** + * Subscription to cloud data changes + * + * @permission ohos.permission.DISTRIBUTED_DATASYNC + * @syscap SystemCapability.DistributedDataManager.CloudSync.Client + * @since 10 + */ + SUBSCRIBE_TYPE_CLOUD, } /** diff --git a/relational_store/interfaces/inner_api/rdb/include/abs_result_set.h b/relational_store/interfaces/inner_api/rdb/include/abs_result_set.h index a3ce68d4..9f2a3469 100644 --- a/relational_store/interfaces/inner_api/rdb/include/abs_result_set.h +++ b/relational_store/interfaces/inner_api/rdb/include/abs_result_set.h @@ -112,7 +112,40 @@ public: */ RDB_API_EXPORT int GetDouble(int columnIndex, double &value) override; + /** + * @brief Obtains the value of the specified column in the current row as asset. + * + * The implementation class determines whether to throw an exception if the value of the specified column + * in the current row is null or the specified column is not of the double type. + * + * @param columnIndex Indicates the specified column index, which starts from 0. + * + * @return Returns the value of the specified column as a double. + */ + RDB_API_EXPORT int GetAsset(int32_t col, ValueObject::Asset &value) override; + + /** + * @brief Obtains the value of the specified column in the current row as assets. + * + * The implementation class determines whether to throw an exception if the value of the specified column + * in the current row is null or the specified column is not of the double type. + * + * @param columnIndex Indicates the specified column index, which starts from 0. + * + * @return Returns the value of the specified column as a double. + */ + RDB_API_EXPORT int GetAssets(int32_t col, ValueObject::Assets &value) override; + + /** + * @brief Get the modify time of the cloud data. + * + * @param modifyTime Indicates the data modify utc time. + * + * @return Returns true if the value of the specified column in the current row is null; + * returns false otherwise. + */ RDB_API_EXPORT int GetModifyTime(std::string &modifyTime) override; + /** * @brief Checks whether the value of the specified column in the current row is null. * diff --git a/relational_store/interfaces/inner_api/rdb/include/abs_shared_result_set.h b/relational_store/interfaces/inner_api/rdb/include/abs_shared_result_set.h index 316dca7b..448e91c3 100644 --- a/relational_store/interfaces/inner_api/rdb/include/abs_shared_result_set.h +++ b/relational_store/interfaces/inner_api/rdb/include/abs_shared_result_set.h @@ -112,6 +112,29 @@ public: */ RDB_API_EXPORT int GetDouble(int columnIndex, double &value) override; + /** + * @brief Obtains the value of the specified column in the current row as asset. + * + * The implementation class determines whether to throw an exception if the value of the specified column + * in the current row is null or the specified column is not of the double type. + * + * @param columnIndex Indicates the specified column index, which starts from 0. + * + * @return Returns the value of the specified column as a double. + */ + RDB_API_EXPORT int GetAsset(int32_t col, ValueObject::Asset &value) override; + + /** + * @brief Obtains the value of the specified column in the current row as assets. + * + * The implementation class determines whether to throw an exception if the value of the specified column + * in the current row is null or the specified column is not of the double type. + * + * @param columnIndex Indicates the specified column index, which starts from 0. + * + * @return Returns the value of the specified column as a double. + */ + RDB_API_EXPORT int GetAssets(int32_t col, ValueObject::Assets &value) override; /** * @brief Checks whether the value of the specified column in the current row is null. diff --git a/relational_store/interfaces/inner_api/rdb/include/asset_value.h b/relational_store/interfaces/inner_api/rdb/include/asset_value.h index 41fa8841..e898bdd3 100644 --- a/relational_store/interfaces/inner_api/rdb/include/asset_value.h +++ b/relational_store/interfaces/inner_api/rdb/include/asset_value.h @@ -16,6 +16,7 @@ #ifndef OHOS_RELATIONAL_STORE_INNER_API_ASSET_VALUE_H #define OHOS_RELATIONAL_STORE_INNER_API_ASSET_VALUE_H #include +#include namespace OHOS::NativeRdb { struct AssetValue { uint32_t version = 0; @@ -25,6 +26,9 @@ struct AssetValue { std::string modifyTime; std::string size; std::string hash; + + std::vector ToRawData(); + size_t FromRawData(const uint8_t *rawData, size_t size); }; } #endif // OHOS_RELATIONAL_STORE_INNER_API_ASSET_VALUE_H diff --git a/relational_store/interfaces/inner_api/rdb/include/result_set.h b/relational_store/interfaces/inner_api/rdb/include/result_set.h index 0b13073a..4e70b2d7 100644 --- a/relational_store/interfaces/inner_api/rdb/include/result_set.h +++ b/relational_store/interfaces/inner_api/rdb/include/result_set.h @@ -16,9 +16,10 @@ #ifndef NATIVE_RDB_RESULT_SET_H #define NATIVE_RDB_RESULT_SET_H +#include #include #include -#include + #include "remote_result_set.h" #include "value_object.h" @@ -31,6 +32,7 @@ public: RDB_API_EXPORT ValueObject Get(const int index) const; RDB_API_EXPORT void Get(std::map &outValues) const; RDB_API_EXPORT void Clear(); + private: std::map values_; std::vector indexs_; @@ -47,6 +49,8 @@ public: */ virtual ~ResultSet() {} + virtual int GetAsset(int32_t col, ValueObject::Asset &value) = 0; + virtual int GetAssets(int32_t col, ValueObject::Assets &value) = 0; /** * @brief Gets the entire row of data for the current row from the result set. */ diff --git a/relational_store/interfaces/inner_api/rdb/include/value_object.h b/relational_store/interfaces/inner_api/rdb/include/value_object.h index 95b2b74f..ed0ac0fb 100644 --- a/relational_store/interfaces/inner_api/rdb/include/value_object.h +++ b/relational_store/interfaces/inner_api/rdb/include/value_object.h @@ -38,15 +38,16 @@ public: using Asset = AssetValue; using Assets = std::vector; using Type = std::variant; + template inline constexpr static size_t TYPE_INDEX = Traits::variant_index_of_v; inline constexpr static size_t TYPE_MAX = Traits::variant_size_of_v; + /** * @brief Indicates the ValueObject {@link ValueObject} type. * */ - enum class TypeId - { + enum TypeId : int32_t { /** Indicates the ValueObject type is NULL.*/ TYPE_NULL = TYPE_INDEX, /** Indicates the ValueObject type is int.*/ @@ -65,7 +66,6 @@ public: TYPE_ASSETS = TYPE_INDEX, TYPE_BUTT }; - Type value; /** @@ -74,6 +74,20 @@ public: template static bool Convert(const _T &input, std::variant<_Rest...> &output); + /** + * @brief convert a std::variant input to another std::variant output with different (..._Types) + */ + static std::vector ToRawData(Asset &asset); + static size_t FromRawData(const uint8_t *rawData, size_t length, Asset &asset); + + /** + * @brief convert a std::variant input to another std::variant output with different (..._Types) + */ + template + static std::enable_if_t < TYPE_MAX, const char *> DeclType() + { + return DECLARE_TYPES[Traits::variant_index_of_v]; + } /** * @brief Constructor. */ @@ -321,6 +335,25 @@ private: } return Get<_T, _O, _Rest...>(input, output); } + + 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.*/ + "INT", + /** Indicates the ValueObject type is blob.*/ + "BLOB", + /** Indicates the ValueObject type is asset.*/ + "ASSET", + /** Indicates the ValueObject type is assets.*/ + "ASSETS" + }; }; template -- Gitee From 1d41ca8bf0e0eb0983f6aee77c0a0c13829061f7 Mon Sep 17 00:00:00 2001 From: Sven Wang Date: Mon, 24 Apr 2023 20:38:44 +0800 Subject: [PATCH 34/44] update Signed-off-by: Sven Wang --- .../native/common/src/shared_blocker.cpp | 4 -- .../native/rdb/src/abs_shared_result_set.cpp | 59 ++++++++++++++----- .../inner_api/rdb/include/rdb_common.h | 1 - .../inner_api/rdb/include/rdb_predicates.h | 2 - .../inner_api/rdb/include/value_object.h | 7 ++- 5 files changed, 49 insertions(+), 24 deletions(-) diff --git a/data_share/frameworks/native/common/src/shared_blocker.cpp b/data_share/frameworks/native/common/src/shared_blocker.cpp index a4050996..52cd0e74 100644 --- a/data_share/frameworks/native/common/src/shared_blocker.cpp +++ b/data_share/frameworks/native/common/src/shared_blocker.cpp @@ -37,11 +37,7 @@ SharedBlocker::~SharedBlocker() if (ashmem_ != nullptr) { ashmem_->UnmapAshmem(); ashmem_->CloseAshmem(); -<<<<<<< HEAD:data_share/frameworks/native/common/src/shared_blocker.cpp LOG_WARN("SharedBlocker: close ashmem"); -======= - LOG_DEBUG("SharedBlock: close ashmem"); ->>>>>>> fcccfeffd0b72b4f1eb7b880b16b8e2b3cec1364:data_share/frameworks/native/common/src/shared_block.cpp } } diff --git a/relational_store/frameworks/native/rdb/src/abs_shared_result_set.cpp b/relational_store/frameworks/native/rdb/src/abs_shared_result_set.cpp index 3d380e9b..eb0c37b7 100644 --- a/relational_store/frameworks/native/rdb/src/abs_shared_result_set.cpp +++ b/relational_store/frameworks/native/rdb/src/abs_shared_result_set.cpp @@ -35,9 +35,7 @@ AbsSharedResultSet::AbsSharedResultSet(std::string name) AppDataFwk::SharedBlock::Create(name, DEFAULT_BLOCK_SIZE, sharedBlock_); } -AbsSharedResultSet::AbsSharedResultSet() -{ -} +AbsSharedResultSet::AbsSharedResultSet() {} AbsSharedResultSet::~AbsSharedResultSet() { @@ -158,8 +156,7 @@ int AbsSharedResultSet::GetBlob(int columnIndex, std::vector &value) value.resize(0); int type = cellUnit->type; - if (type == AppDataFwk::SharedBlock::CELL_UNIT_TYPE_BLOB - || type == AppDataFwk::SharedBlock::CELL_UNIT_TYPE_STRING) { + if (type == AppDataFwk::SharedBlock::CELL_UNIT_TYPE_BLOB || type == AppDataFwk::SharedBlock::CELL_UNIT_TYPE_STRING) { size_t size; const auto *blob = static_cast(sharedBlock_->GetCellUnitValueBlob(cellUnit, &size)); if (size == 0 || blob == nullptr) { @@ -326,26 +323,56 @@ int AbsSharedResultSet::GetAsset(int32_t col, ValueObject::Asset &value) if (errorCode != E_OK) { return errorCode; } + AppDataFwk::SharedBlock::CellUnit *cellUnit = sharedBlock_->GetCellUnit(sharedBlock_->GetBlockPos(), col); if (!cellUnit) { - LOG_ERROR("AbsSharedResultSet::GetDouble cellUnit is null!"); + LOG_ERROR("GetAsset cellUnit is null!"); return E_ERROR; } - int type = cellUnit->type; - if (type == AppDataFwk::SharedBlock::CELL_UNIT_TYPE_ASSET) { - size_t size = 0; - auto data = reinterpret_cast(sharedBlock_->GetCellUnitValueBlob(cellUnit, &size)); - ValueObject::Asset asset; - ValueObject::FromRawData(data, size, asset); - } else { - LOG_ERROR("AbsSharedResultSet::GetDouble AppDataFwk::SharedBlock::nothing !"); + + if (cellUnit->type != AppDataFwk::SharedBlock::CELL_UNIT_TYPE_ASSET) { + LOG_ERROR("GetAsset AppDataFwk::SharedBlock::nothing !"); return E_INVALID_OBJECT_TYPE; } + + size_t size = 0; + auto data = reinterpret_cast(sharedBlock_->GetCellUnitValueBlob(cellUnit, &size)); + ValueObject::Asset asset; + ValueObject::FromRawData(data, size, asset); + value = std::move(asset); + return E_OK; } int AbsSharedResultSet::GetAssets(int32_t col, ValueObject::Assets &value) { - return AbsResultSet::GetAssets(col, value); + DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__)); + int errorCode = CheckState(col); + if (errorCode != E_OK) { + return errorCode; + } + + auto *cellUnit = sharedBlock_->GetCellUnit(sharedBlock_->GetBlockPos(), col); + if (!cellUnit) { + LOG_ERROR("GetAssets cellUnit is null!"); + return E_ERROR; + } + + if (cellUnit->type != AppDataFwk::SharedBlock::CELL_UNIT_TYPE_ASSETS) { + LOG_ERROR("GetAssets AppDataFwk::SharedBlock::nothing !"); + return E_INVALID_OBJECT_TYPE; + } + + size_t size = 0; + auto data = reinterpret_cast(sharedBlock_->GetCellUnitValueBlob(cellUnit, &size)); + size_t offset = 0; + ValueObject::Assets assets; + for (int i = 0; i < ; ++i) { + ValueObject::Asset asset; + offset += ValueObject::FromRawData(&data[offset], size, asset); + assets.push_back(std::move(asset)); + } + value = std::move(assets); + return E_OK; } int AbsSharedResultSet::IsColumnNull(int columnIndex, bool &isNull) @@ -428,7 +455,7 @@ int AbsSharedResultSet::CheckState(int columnIndex) if (rowPos_ < 0 || rowPos_ >= count) { return E_INVALID_STATEMENT; } - + GetColumnCount(count); if (columnIndex >= count || columnIndex < 0) { return E_INVALID_COLUMN_INDEX; diff --git a/relational_store/interfaces/inner_api/rdb/include/rdb_common.h b/relational_store/interfaces/inner_api/rdb/include/rdb_common.h index 766d7f01..2c9b1c0e 100644 --- a/relational_store/interfaces/inner_api/rdb/include/rdb_common.h +++ b/relational_store/interfaces/inner_api/rdb/include/rdb_common.h @@ -34,5 +34,4 @@ enum class ConflictResolution { }; } } - #endif // NATIVE_RDB_RDB_COMMON_H diff --git a/relational_store/interfaces/inner_api/rdb/include/rdb_predicates.h b/relational_store/interfaces/inner_api/rdb/include/rdb_predicates.h index 0c6a7a4b..bdff3871 100644 --- a/relational_store/interfaces/inner_api/rdb/include/rdb_predicates.h +++ b/relational_store/interfaces/inner_api/rdb/include/rdb_predicates.h @@ -15,8 +15,6 @@ #ifndef NATIVE_RDB_RDBPREDICATES_H #define NATIVE_RDB_RDBPREDICATES_H - - #include "abs_rdb_predicates.h" #include "rdb_visibility.h" diff --git a/relational_store/interfaces/inner_api/rdb/include/value_object.h b/relational_store/interfaces/inner_api/rdb/include/value_object.h index ed0ac0fb..c407b3a2 100644 --- a/relational_store/interfaces/inner_api/rdb/include/value_object.h +++ b/relational_store/interfaces/inner_api/rdb/include/value_object.h @@ -84,7 +84,7 @@ public: * @brief convert a std::variant input to another std::variant output with different (..._Types) */ template - static std::enable_if_t < TYPE_MAX, const char *> DeclType() + static inline std::enable_if_t < TYPE_INDEX DeclType() { return DECLARE_TYPES[Traits::variant_index_of_v]; } @@ -219,14 +219,17 @@ public: * @brief Obtains the vector value in this {@code ValueObject} object. */ RDB_API_EXPORT int GetBlob(std::vector &val) const; + /** * @brief Obtains the vector value in this {@code ValueObject} object. */ RDB_API_EXPORT int GetAsset(Asset &val) const; + /** * @brief Obtains the vector value in this {@code ValueObject} object. */ RDB_API_EXPORT int GetAssets(Assets &val) const; + /** * @brief Type conversion function. * @@ -296,6 +299,7 @@ public: { return std::get(value); } + /** * @brief Type conversion function. * @@ -305,6 +309,7 @@ public: { return std::get(value); } + /** * @brief Type conversion function. * -- Gitee From f5f5e43dc2ae528ac12fc248b7678fc179d6bb82 Mon Sep 17 00:00:00 2001 From: Sven Wang Date: Tue, 25 Apr 2023 10:17:13 +0800 Subject: [PATCH 35/44] update Signed-off-by: Sven Wang --- .clang-format | 1 + data_object/.clang-format | 187 ------------------ .../framework/include/cloud/asset_loader.h | 2 +- .../framework/include/cloud/cloud_server.h | 8 +- .../framework/include/store/general_value.h | 3 +- googletest/.clang-format | 4 - .../native/rdb/src/abs_shared_result_set.cpp | 2 +- 7 files changed, 8 insertions(+), 199 deletions(-) delete mode 100644 data_object/.clang-format delete mode 100644 googletest/.clang-format diff --git a/.clang-format b/.clang-format index 53e7a399..c0aa629a 100644 --- a/.clang-format +++ b/.clang-format @@ -34,6 +34,7 @@ AllowAllParametersOfDeclarationOnNextLine: false # 枚举值不会在一行 AllowShortEnumsOnASingleLine: false +# 短语句不会在一行 AllowShortBlocksOnASingleLine: false # 允许短的case标签放在同一行 diff --git a/data_object/.clang-format b/data_object/.clang-format deleted file mode 100644 index acad2013..00000000 --- a/data_object/.clang-format +++ /dev/null @@ -1,187 +0,0 @@ -Language: Cpp - -AccessModifierOffset: -4 - -AlignAfterOpenBracket: DontAlign - -AlignConsecutiveAssignments: false - -AlignConsecutiveDeclarations: false - -AlignOperands: true - -AlignTrailingComments: true - -AllowAllParametersOfDeclarationOnNextLine: false -AllowShortBlocksOnASingleLine: false - -AllowShortCaseLabelsOnASingleLine: false - -AllowShortFunctionsOnASingleLine: None - -AllowShortIfStatementsOnASingleLine: false - -AllowShortLoopsOnASingleLine: false - -AlwaysBreakAfterDefinitionReturnType: None - -AlwaysBreakAfterReturnType: None - -AlwaysBreakBeforeMultilineStrings: false - -AlwaysBreakTemplateDeclarations: false - -BinPackArguments: true - -BinPackParameters: true - -BreakBeforeBinaryOperators: NonAssignment - -BreakBeforeBraces: Custom - -AlignEscapedNewlines: Left - -BreakBeforeInheritanceComma: false - -BreakBeforeTernaryOperators: true - -BreakConstructorInitializersBeforeComma: false -BreakConstructorInitializers: BeforeColon - -BreakInheritanceList: BeforeComma -BreakAfterJavaFieldAnnotations: false -BreakStringLiterals: true - -ColumnLimit: 119 - -CommentPragmas: '^ NOLINT' -CompactNamespaces: false - -ConstructorInitializerAllOnOneLineOrOnePerLine: false - -ConstructorInitializerIndentWidth: 4 - -ContinuationIndentWidth: 4 -Cpp11BracedListStyle: false - -DerivePointerAlignment: false - -PointerAlignment: Right - -ExperimentalAutoDetectBinPacking: false - -FixNamespaceComments: true - -ForEachMacros: - - foreach - - Q_FOREACH - - BOOST_FOREACH -IncludeBlocks: Regroup - -IncludeCategories: - - Regex: '^' - Priority: 2 - - Regex: '^<.*\.h>' - Priority: 1 - - Regex: '^<.*' - Priority: 2 - - Regex: '.*' - Priority: 3 -IncludeIsMainRegex: '([-_](test|benchmark))?$' - -IndentCaseLabels: true -IndentPPDirectives: None - -IndentWidth: 4 - -IndentWrappedFunctionNames: false - -JavaScriptQuotes: Leave -JavaScriptWrapImports: true - -KeepEmptyLinesAtTheStartOfBlocks: false - -MacroBlockBegin: '[A-Z_]+_BEGIN\(.*\)$' - -MacroBlockEnd: '.[A-Z_]+_END\(.*\)$' - -MaxEmptyLinesToKeep: 1 - -NamespaceIndentation: None - -ObjCBinPackProtocolList: Never - -ObjCBlockIndentWidth: 4 - -ObjCSpaceAfterProperty: false - -ObjCSpaceBeforeProtocolList: true - -PenaltyBreakBeforeFirstCallParameter: 1000 - -PenaltyBreakComment: 100 - -PenaltyBreakFirstLessLess: 5 - -PenaltyBreakString: 10 - -PenaltyBreakTemplateDeclaration: 10 - -PenaltyExcessCharacter: 20 - -PenaltyReturnTypeOnItsOwnLine: 50 - -PenaltyBreakAssignment: 10 - -ReflowComments: false - -SortIncludes: true - -SortUsingDeclarations: true - -SpaceAfterCStyleCast: false - -SpaceAfterTemplateKeyword: false - -SpaceBeforeAssignmentOperators: true -SpaceBeforeCpp11BracedList: false -SpaceBeforeCtorInitializerColon: true -SpaceBeforeInheritanceColon: true - -SpaceBeforeParens: ControlStatements -SpaceBeforeRangeBasedForLoopColon: true - -SpaceInEmptyParentheses: false - -SpacesBeforeTrailingComments: 1 - -SpacesInAngles: false - -SpacesInContainerLiterals: true - -SpacesInCStyleCastParentheses: false - -SpacesInParentheses: false - -SpacesInSquareBrackets: false - -Standard: Cpp11 - -TabWidth: 4 - -UseTab: Never - -BraceWrapping: - AfterClass: false - AfterControlStatement: false - AfterEnum: false - AfterFunction: true - AfterNamespace: false - AfterObjCDeclaration: false - AfterStruct: false - AfterUnion: false - AfterExternBlock: false - BeforeCatch: false - BeforeElse: false - -DisableFormat: false diff --git a/datamgr_service/services/distributeddataservice/framework/include/cloud/asset_loader.h b/datamgr_service/services/distributeddataservice/framework/include/cloud/asset_loader.h index ec3b9a80..8e43f360 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/cloud/asset_loader.h +++ b/datamgr_service/services/distributeddataservice/framework/include/cloud/asset_loader.h @@ -19,7 +19,7 @@ namespace OHOS::DistributedData { class AssetLoader { public: - virtual ~AssetLoader() = 0; + virtual ~AssetLoader() = default; virtual int32_t Upload(const std::vector &assets) = 0; virtual int32_t Download(std::vector &assets) = 0; }; diff --git a/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_server.h b/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_server.h index 2197efa6..d055c675 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_server.h +++ b/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_server.h @@ -27,10 +27,10 @@ public: API_EXPORT static CloudServer *GetInstance(); API_EXPORT static bool RegisterCloudInstance(CloudServer *instance); - virtual CloudInfo GetServerInfo(int32_t userId); - virtual SchemaMeta GetAppSchema(int32_t userId, const std::string &bundleName); - virtual std::shared_ptr ConnectAssetLoader(uint32_t tokenId, const Database &dbMeta); - virtual std::shared_ptr ConnectCloudDB(uint32_t tokenId, const Database &dbMeta); + virtual CloudInfo GetServerInfo(int32_t userId) = 0; + virtual SchemaMeta GetAppSchema(int32_t userId, const std::string &bundleName) = 0; + virtual std::shared_ptr ConnectAssetLoader(uint32_t tokenId, const Database &dbMeta) = 0; + virtual std::shared_ptr ConnectCloudDB(uint32_t tokenId, const Database &dbMeta) = 0; private: static CloudServer *instance_; diff --git a/datamgr_service/services/distributeddataservice/framework/include/store/general_value.h b/datamgr_service/services/distributeddataservice/framework/include/store/general_value.h index a3acb79f..108ca00d 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/store/general_value.h +++ b/datamgr_service/services/distributeddataservice/framework/include/store/general_value.h @@ -22,8 +22,7 @@ #include #include "traits.h" namespace OHOS::DistributedData { -enum GeneralError : int32_t -{ +enum GeneralError : int32_t { E_OK = 0, E_ERROR, E_BUSY, diff --git a/googletest/.clang-format b/googletest/.clang-format deleted file mode 100644 index 5b9bfe6d..00000000 --- a/googletest/.clang-format +++ /dev/null @@ -1,4 +0,0 @@ -# Run manually to reformat a file: -# clang-format -i --style=file -Language: Cpp -BasedOnStyle: Google diff --git a/relational_store/frameworks/native/rdb/src/abs_shared_result_set.cpp b/relational_store/frameworks/native/rdb/src/abs_shared_result_set.cpp index eb0c37b7..2e2ead4f 100644 --- a/relational_store/frameworks/native/rdb/src/abs_shared_result_set.cpp +++ b/relational_store/frameworks/native/rdb/src/abs_shared_result_set.cpp @@ -366,7 +366,7 @@ int AbsSharedResultSet::GetAssets(int32_t col, ValueObject::Assets &value) auto data = reinterpret_cast(sharedBlock_->GetCellUnitValueBlob(cellUnit, &size)); size_t offset = 0; ValueObject::Assets assets; - for (int i = 0; i < ; ++i) { + while (offset < size) { ValueObject::Asset asset; offset += ValueObject::FromRawData(&data[offset], size, asset); assets.push_back(std::move(asset)); -- Gitee From 495e8086c1ebb1fe04401eedd0411da64839120b Mon Sep 17 00:00:00 2001 From: zuojiangjiang Date: Tue, 25 Apr 2023 10:42:47 +0800 Subject: [PATCH 36/44] update Signed-off-by: zuojiangjiang --- .../framework/cloud/cloud_info.cpp | 14 ++-- .../framework/include/cloud/cloud_info.h | 2 +- .../service/cloud/cloud_service_impl.cpp | 69 ++----------------- .../service/cloud/cloud_service_impl.h | 5 +- .../service/cloud/cloud_service_stub.cpp | 25 ------- .../service/cloud/cloud_service_stub.h | 2 - .../service/rdb/rdb_service_impl.cpp | 8 +-- .../cloud_data/include/cloud_service_proxy.h | 2 - .../cloud_data/src/cloud_service_proxy.cpp | 23 ------- .../cloud_data/include/cloud_service.h | 4 -- 10 files changed, 20 insertions(+), 134 deletions(-) diff --git a/datamgr_service/services/distributeddataservice/framework/cloud/cloud_info.cpp b/datamgr_service/services/distributeddataservice/framework/cloud/cloud_info.cpp index e8d83c18..be368f11 100644 --- a/datamgr_service/services/distributeddataservice/framework/cloud/cloud_info.cpp +++ b/datamgr_service/services/distributeddataservice/framework/cloud/cloud_info.cpp @@ -92,15 +92,17 @@ bool CloudInfo::IsExist(const std::string &bundleName) const return false; } -void CloudInfo::DelApp(const std::string &bundleName) +void CloudInfo::UpdateApp(const std::vector &appInfos) { - for (auto it = apps.begin(); it != apps.end();) { - if (it->bundleName == bundleName) { - it = apps.erase(it); - break; + auto tmpInfo = appInfos; + for (auto &info : tmpInfo) { + auto app = GetApp(info.bundleName); + if (app.bundleName.empty()) { + continue; } - it++; + info.cloudSwitch = app.cloudSwitch; } + apps = tmpInfo; } CloudInfo::AppInfo &CloudInfo::GetApp(const std::string &bundleName) diff --git a/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_info.h b/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_info.h index f87c1d03..c7d2cd17 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_info.h +++ b/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_info.h @@ -40,7 +40,7 @@ public: std::string GetSchemaKey(std::string bundleName) const; bool IsValid() const; bool IsExist(const std::string &bundleName) const; - void DelApp(const std::string &bundleName); + void UpdateApp(const std::vector &appInfos); AppInfo &GetApp(const std::string &bundleName); static std::string GetPrefix(const std::initializer_list &field); diff --git a/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.cpp b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.cpp index 0cf1ebe7..bc24bd44 100644 --- a/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.cpp +++ b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.cpp @@ -56,6 +56,7 @@ CloudServiceImpl::CloudServiceImpl() } UpdateCloudInfo(cloudInfo); AddSchema(cloudInfo); + // TODO: Clear Task }); EventCenter::GetInstance().Subscribe(CloudEvent::GET_SCHEMA, [this](const Event &event) { @@ -95,7 +96,7 @@ int32_t CloudServiceImpl::EnableCloud(const std::string &id, const std::map lg(mutex_); CloudInfo cloudInfo; cloudInfo.id = id; - if (GetCloudInfo(cloudInfo) != SUCCESS) { + if (GetCloudInfo(cloudInfo) != SUCCESS && GetServerInfo(cloudInfo) != SUCCESS) { return INVALID_ARGUMENT; } cloudInfo.enableCloud = true; @@ -113,7 +114,7 @@ int32_t CloudServiceImpl::DisableCloud(const std::string &id) std::lock_guard lg(mutex_); CloudInfo cloudInfo; cloudInfo.id = id; - if (GetCloudInfo(cloudInfo) != SUCCESS) { + if (GetCloudInfo(cloudInfo) != SUCCESS && GetServerInfo(cloudInfo) != SUCCESS) { return INVALID_ARGUMENT; } cloudInfo.enableCloud = false; @@ -128,7 +129,7 @@ int32_t CloudServiceImpl::ChangeAppSwitch(const std::string &id, const std::stri std::lock_guard lg(mutex_); CloudInfo cloudInfo; cloudInfo.id = id; - if (GetCloudInfo(cloudInfo) != SUCCESS) { + if (GetCloudInfo(cloudInfo) != SUCCESS && GetServerInfo(cloudInfo) != SUCCESS) { return INVALID_ARGUMENT; } auto &app = cloudInfo.GetApp(bundleName); @@ -147,7 +148,7 @@ int32_t CloudServiceImpl::Clean(const std::string &id, const std::mapGetUserByToken(tokenId); - if (ConfigCloudInfo(storeInfo, cloudInfo) != SUCCESS) { - return ERROR; - } - UpdateSchema(cloudInfo, storeInfo, storeInfo.version); - if (GetStoreSchema(cloudInfo, storeInfo, schema) != SUCCESS) { - return ERROR; - } - return SUCCESS; -} - -int32_t CloudServiceImpl::ConfigCloudInfo(const StoreInfo &storeInfo, CloudInfo &cloudInfo) -{ - if (GetCloudInfo(cloudInfo) != SUCCESS && GetServerInfo(cloudInfo) != SUCCESS) { - ZLOGE("id:%{public}s", Anonymous::Change(cloudInfo.id).c_str()); - return ERROR; - } - if (!cloudInfo.IsExist(storeInfo.bundleName)) { - CloudInfo::AppInfo appInfo; - appInfo.bundleName = storeInfo.bundleName; - appInfo.appId = GetAppId(storeInfo.bundleName); - cloudInfo.apps.emplace_back(appInfo); - } - MetaDataManager::GetInstance().SaveMeta(cloudInfo.GetKey(), cloudInfo, true); - return SUCCESS; -} - int32_t CloudServiceImpl::GetStoreSchema(const CloudInfo &cloudInfo, const StoreInfo &storeInfo, std::string &schema) { if (!cloudInfo.IsExist(storeInfo.bundleName)) { @@ -226,27 +191,6 @@ int32_t CloudServiceImpl::GetStoreSchema(const CloudInfo &cloudInfo, const Store return SUCCESS; } -int32_t CloudServiceImpl::ClearConfig(const std::string &id, const StoreInfo &storeInfo) -{ - if (!CheckAccess(storeInfo.bundleName)) { - ZLOGE("permission denied"); - return ERROR; - } - - CloudInfo cloudInfo; - cloudInfo.id = id; - if (GetCloudInfo(cloudInfo) != SUCCESS) { - ZLOGE("id:%{public}s", Anonymous::Change(cloudInfo.id).c_str()); - return ERROR; - } - if (cloudInfo.IsExist(storeInfo.bundleName)) { - auto keys = cloudInfo.GetSchemaKey(); - MetaDataManager::GetInstance().DelMeta(keys[storeInfo.bundleName], true); - cloudInfo.DelApp(storeInfo.bundleName); - } - return SUCCESS; -} - int32_t CloudServiceImpl::GetCloudInfo(CloudInfo &cloudInfo) { auto tokenId = IPCSkeleton::GetCallingTokenID(); @@ -299,6 +243,7 @@ void CloudServiceImpl::UpdateCloudInfo(CloudInfo &cloudInfo) } oldInfo.totalSpace = cloudInfo.totalSpace; oldInfo.remainSpace = cloudInfo.remainSpace; + oldInfo.UpdateApp(cloudInfo.apps); cloudInfo = oldInfo; MetaDataManager::GetInstance().SaveMeta(oldInfo.GetKey(), oldInfo, true); } diff --git a/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.h b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.h index 0df774ea..097f2719 100644 --- a/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.h +++ b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.h @@ -31,8 +31,6 @@ public: int32_t ChangeAppSwitch(const std::string &id, const std::string &bundleName, int32_t appSwitch) override; int32_t Clean(const std::string &id, const std::map &actions) override; int32_t NotifyDataChange(const std::string &id, const std::string &bundleName) override; - int32_t Config(const std::string &id, const StoreInfo &storeInfo, std::string &schema) override; - int32_t ClearConfig(const std::string &id, const StoreInfo &storeInfo) override; private: class Factory { @@ -50,7 +48,6 @@ private: void UpdateCloudInfo(CloudInfo &cloudInfo); void AddSchema(CloudInfo &cloudInfo); void UpdateSchema(CloudInfo &cloudInfo, const StoreInfo &storeInfo, int32_t version); - int32_t ConfigCloudInfo(const StoreInfo &storeInfo, CloudInfo &cloudInfo); int32_t GetStoreSchema(const CloudInfo &cloudInfo, const StoreInfo &storeInfo, std::string &schema); int32_t GetCloudInfo(CloudInfo &cloudInfo); int32_t GetServerInfo(CloudInfo &cloudInfo); @@ -58,7 +55,7 @@ private: std::string GetAppId(const std::string &bundleName); bool CheckAccess(const std::string &bundleName); std::mutex mutex_; - ConcurrentMap clousInfos_; + ConcurrentMap cloudInfos_; }; } // namespace OHOS::DistributedData diff --git a/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_stub.cpp b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_stub.cpp index ae472364..2ccf869e 100644 --- a/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_stub.cpp +++ b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_stub.cpp @@ -27,8 +27,6 @@ const CloudServiceStub::Handler CloudServiceStub::HANDLERS[TRANS_BUTT] = { &CloudServiceStub::OnChangeAppSwitch, &CloudServiceStub::OnClean, &CloudServiceStub::OnNotifyDataChange, - &CloudServiceStub::OnConfig, - &CloudServiceStub::OnClearConfig, }; int CloudServiceStub::OnRemoteRequest(uint32_t code, OHOS::MessageParcel &data, OHOS::MessageParcel &reply) @@ -103,27 +101,4 @@ int32_t CloudServiceStub::OnNotifyDataChange(const std::string &id, MessageParce auto result = NotifyDataChange(id, bundleName); return ITypesUtil::Marshal(reply, result) ? ERR_NONE : IPC_STUB_WRITE_PARCEL_ERR; } - -int32_t CloudServiceStub::OnConfig(const std::string &id, MessageParcel &data, MessageParcel &reply) -{ - StoreInfo storeInfo; - if (!ITypesUtil::Unmarshal(data, storeInfo)) { - ZLOGE("Unmarshal id:%{public}s", Anonymous::Change(id).c_str()); - return IPC_STUB_INVALID_DATA_ERR; - } - std::string schema; - auto result = Config(id, storeInfo, schema); - return ITypesUtil::Marshal(reply, result, schema) ? ERR_NONE : IPC_STUB_WRITE_PARCEL_ERR; -} - -int32_t CloudServiceStub::OnClearConfig(const std::string &id, MessageParcel &data, MessageParcel &reply) -{ - StoreInfo storeInfo; - if (!ITypesUtil::Unmarshal(data, storeInfo)) { - ZLOGE("Unmarshal id:%{public}s", Anonymous::Change(id).c_str()); - return IPC_STUB_INVALID_DATA_ERR; - } - auto result = ClearConfig(id, storeInfo); - return ITypesUtil::Marshal(reply, result) ? ERR_NONE : IPC_STUB_WRITE_PARCEL_ERR; -} } // namespace OHOS::CloudData diff --git a/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_stub.h b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_stub.h index f1f3cd62..4175015d 100644 --- a/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_stub.h +++ b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_stub.h @@ -31,8 +31,6 @@ private: int32_t OnChangeAppSwitch(const std::string &id, MessageParcel &data, MessageParcel &reply); int32_t OnClean(const std::string &id, MessageParcel &data, MessageParcel &reply); int32_t OnNotifyDataChange(const std::string &id, MessageParcel &data, MessageParcel &reply); - int32_t OnConfig(const std::string &id, MessageParcel &data, MessageParcel &reply); - int32_t OnClearConfig(const std::string &id, MessageParcel &data, MessageParcel &reply); static const Handler HANDLERS[TRANS_BUTT]; }; } // namespace OHOS::CloudData diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.cpp b/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.cpp index ccb7f2d0..8f98b6d4 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.cpp +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.cpp @@ -471,8 +471,7 @@ int32_t RdbServiceImpl::DestroyRDBTable(const RdbSyncerParam ¶m) int32_t RdbServiceImpl::OnInitialize() { auto tokenId = IPCSkeleton::GetCallingTokenID(); - auto user = AccountDelegate::GetInstance()->GetUserByToken(tokenId); - auto initEvt = std::make_unique(CloudEvent::FEATURE_INIT, user); + auto initEvt = std::make_unique(CloudEvent::FEATURE_INIT, tokenId); EventCenter::GetInstance().PostEvent(std::move(initEvt)); return RDB_OK; } @@ -485,9 +484,8 @@ int32_t RdbServiceImpl::GetSchema(const std::string &bundleName, const std::stri } auto event = std::make_unique(CloudEvent::GET_SCHEMA, IPCSkeleton::GetCallingTokenID(), storeName, bundleName); - EventCenter::GetInstance().PostEvent(move(event)); - - return 0; + EventCenter::GetInstance().PostEvent(std::move(event)); + return RDB_OK; } } // namespace OHOS::DistributedRdb diff --git a/relational_store/frameworks/native/cloud_data/include/cloud_service_proxy.h b/relational_store/frameworks/native/cloud_data/include/cloud_service_proxy.h index 0c6e7844..7dec3bf8 100644 --- a/relational_store/frameworks/native/cloud_data/include/cloud_service_proxy.h +++ b/relational_store/frameworks/native/cloud_data/include/cloud_service_proxy.h @@ -30,8 +30,6 @@ public: int32_t ChangeAppSwitch(const std::string &id, const std::string &bundleName, int32_t appSwitch) override; int32_t Clean(const std::string &id, const std::map &actions) override; int32_t NotifyDataChange(const std::string &id, const std::string &bundleName) override; - int32_t Config(const std::string &id, const StoreInfo &storeInfo, std::string &schema) override; - int32_t ClearConfig(const std::string &id, const StoreInfo &storeInfo) override; private: sptr remote_; diff --git a/relational_store/frameworks/native/cloud_data/src/cloud_service_proxy.cpp b/relational_store/frameworks/native/cloud_data/src/cloud_service_proxy.cpp index 833cb5a3..fd295595 100644 --- a/relational_store/frameworks/native/cloud_data/src/cloud_service_proxy.cpp +++ b/relational_store/frameworks/native/cloud_data/src/cloud_service_proxy.cpp @@ -102,27 +102,4 @@ int32_t CloudServiceProxy::NotifyDataChange(const std::string &id, const std::st } return static_cast(status); } - -int32_t CloudServiceProxy::Config(const std::string &id, const StoreInfo &storeInfo, std::string &schema) -{ - MessageParcel reply; - int32_t status = IPC_SEND(TRANS_CONFIG, reply, id, storeInfo); - if (status != SUCCESS) { - ZLOGE("status:0x%{public}x id:%{public}.6s bundleName:%{public}s, storeId:%{public}s", - status, id.c_str(), storeInfo.bundleName.c_str(), storeInfo.storeId.c_str()); - } - ITypesUtil::Unmarshal(reply, schema); - return static_cast(status); -} - -int32_t CloudServiceProxy::ClearConfig(const std::string &id, const StoreInfo &storeInfo) -{ - MessageParcel reply; - int32_t status = IPC_SEND(TRANS_CLEAR_CONFIG, reply, id, storeInfo); - if (status != SUCCESS) { - ZLOGE("status:0x%{public}x id:%{public}.6s bundleName:%{public}s, storeId:%{public}s", - status, id.c_str(), storeInfo.bundleName.c_str(), storeInfo.storeId.c_str()); - } - return static_cast(status); -} } // namespace OHOS::CloudData \ No newline at end of file diff --git a/relational_store/interfaces/inner_api/cloud_data/include/cloud_service.h b/relational_store/interfaces/inner_api/cloud_data/include/cloud_service.h index 83792cf6..a1b69ce2 100644 --- a/relational_store/interfaces/inner_api/cloud_data/include/cloud_service.h +++ b/relational_store/interfaces/inner_api/cloud_data/include/cloud_service.h @@ -30,8 +30,6 @@ public: TRANS_CHANGE_APP_SWITCH, TRANS_CLEAN, TRANS_NOTIFY_DATA_CHANGE, - TRANS_CONFIG, - TRANS_CLEAR_CONFIG, TRANS_BUTT, }; enum Action : int32_t @@ -69,8 +67,6 @@ public: virtual int32_t ChangeAppSwitch(const std::string &id, const std::string &bundleName, int32_t appSwitch) = 0; virtual int32_t Clean(const std::string &id, const std::map &actions) = 0; virtual int32_t NotifyDataChange(const std::string &id, const std::string &bundleName) = 0; - virtual int32_t Config(const std::string &id, const StoreInfo &storeInfo, std::string &schema) = 0; - virtual int32_t ClearConfig(const std::string &id, const StoreInfo &storeInfo) = 0; static constexpr const char *SERVICE_NAME = "cloud"; }; -- Gitee From d730ec460e4bcf4beaa9c32b469372cf245f6577 Mon Sep 17 00:00:00 2001 From: zuojiangjiang Date: Tue, 25 Apr 2023 11:12:17 +0800 Subject: [PATCH 37/44] update Signed-off-by: zuojiangjiang --- .../service/cloud/cloud_service_impl.cpp | 48 ------------------- .../service/cloud/cloud_service_impl.h | 2 - .../cloud_data/include/cloud_types_util.h | 30 ------------ .../cloud_data/src/cloud_types_util.cpp | 30 ------------ .../cloud_data/include/cloud_service.h | 6 --- 5 files changed, 116 deletions(-) delete mode 100644 relational_store/frameworks/native/cloud_data/include/cloud_types_util.h delete mode 100644 relational_store/frameworks/native/cloud_data/src/cloud_types_util.cpp diff --git a/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.cpp b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.cpp index bc24bd44..334f7277 100644 --- a/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.cpp +++ b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.cpp @@ -170,27 +170,6 @@ int32_t CloudServiceImpl::NotifyDataChange(const std::string &id, const std::str return 0; } -int32_t CloudServiceImpl::GetStoreSchema(const CloudInfo &cloudInfo, const StoreInfo &storeInfo, std::string &schema) -{ - if (!cloudInfo.IsExist(storeInfo.bundleName)) { - ZLOGE("no exist bundleName:%{public}s", storeInfo.bundleName.c_str()); - return ERROR; - } - SchemaMeta schemaMeta; - auto keys = cloudInfo.GetSchemaKey(); - if (!MetaDataManager::GetInstance().LoadMeta(keys[storeInfo.bundleName], schemaMeta, true)) { - ZLOGE("schema empty bundleName:%{public}s", storeInfo.bundleName.c_str()); - return ERROR; - } - auto database = schemaMeta.GetDataBase(storeInfo.storeId); - if (database.name.empty()) { - ZLOGE("storeId:%{public}s", storeInfo.storeId.c_str()); - return ERROR; - } - schema = Serializable::Marshall(database); - return SUCCESS; -} - int32_t CloudServiceImpl::GetCloudInfo(CloudInfo &cloudInfo) { auto tokenId = IPCSkeleton::GetCallingTokenID(); @@ -272,31 +251,4 @@ int32_t CloudServiceImpl::GetAppSchema(int32_t user, const std::string &bundleNa schemaMeta = instance->GetAppSchema(user, bundleName); return SUCCESS; } - -void CloudServiceImpl::UpdateSchema(CloudInfo &cloudInfo, const StoreInfo &storeInfo, int32_t version) -{ - SchemaMeta schemaMeta; - auto key = cloudInfo.GetSchemaKey(storeInfo.bundleName); - if (!MetaDataManager::GetInstance().LoadMeta(key, schemaMeta, true)) { - if (GetAppSchema(cloudInfo.user, storeInfo.bundleName, schemaMeta) != SUCCESS) { - ZLOGI("get schema meta fail"); - return; - } - MetaDataManager::GetInstance().SaveMeta(key, schemaMeta, true); - } - if (version <= schemaMeta.version) { - ZLOGI("input ver:%{public}d, meta ver:%{public}d", version, schemaMeta.version); - return; - } - SchemaMeta serverMeta; - if (GetAppSchema(cloudInfo.user, storeInfo.bundleName, serverMeta) != SUCCESS) { - ZLOGI("get schema meta fail"); - return; - } - if (serverMeta.version != version) { - ZLOGI("input ver:%{public}d, server ver:%{public}d", version, serverMeta.version); - return; - } - MetaDataManager::GetInstance().SaveMeta(key, serverMeta, true); -} } // namespace OHOS::CloudData \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.h b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.h index 097f2719..80aa5100 100644 --- a/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.h +++ b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.h @@ -47,8 +47,6 @@ private: void UpdateCloudInfo(CloudInfo &cloudInfo); void AddSchema(CloudInfo &cloudInfo); - void UpdateSchema(CloudInfo &cloudInfo, const StoreInfo &storeInfo, int32_t version); - int32_t GetStoreSchema(const CloudInfo &cloudInfo, const StoreInfo &storeInfo, std::string &schema); int32_t GetCloudInfo(CloudInfo &cloudInfo); int32_t GetServerInfo(CloudInfo &cloudInfo); int32_t GetAppSchema(int32_t user, const std::string &bundleName, SchemaMeta &schemaMeta); diff --git a/relational_store/frameworks/native/cloud_data/include/cloud_types_util.h b/relational_store/frameworks/native/cloud_data/include/cloud_types_util.h deleted file mode 100644 index 8dbd969d..00000000 --- a/relational_store/frameworks/native/cloud_data/include/cloud_types_util.h +++ /dev/null @@ -1,30 +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_DISTRIBUTED_DATA_CLOUD_CLOUD_TYPES_UTIL_H -#define OHOS_DISTRIBUTED_DATA_CLOUD_CLOUD_TYPES_UTIL_H - -#include "cloud_service.h" -#include "itypes_util.h" -#include "rdb_visibility.h" - -namespace OHOS::ITypesUtil { -using StoreInfo = CloudData::CloudService::StoreInfo; -template<> -RDB_API_EXPORT bool Marshalling(const StoreInfo &input, MessageParcel &data); -template<> -RDB_API_EXPORT bool Unmarshalling(StoreInfo &output, MessageParcel &data); -} // namespace OHOS::ITypesUtil -#endif // OHOS_DISTRIBUTED_DATA_CLOUD_CLOUD_TYPES_UTIL_H diff --git a/relational_store/frameworks/native/cloud_data/src/cloud_types_util.cpp b/relational_store/frameworks/native/cloud_data/src/cloud_types_util.cpp deleted file mode 100644 index d127971f..00000000 --- a/relational_store/frameworks/native/cloud_data/src/cloud_types_util.cpp +++ /dev/null @@ -1,30 +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. - */ - -#include "cloud_types_util.h" - -namespace OHOS::ITypesUtil { -template<> -bool Marshalling(const StoreInfo &input, MessageParcel &data) -{ - return ITypesUtil::Marshal(data, input.bundleName, input.storeId, input.version); -} -template<> -bool Unmarshalling(StoreInfo &output, MessageParcel &data) -{ - return ITypesUtil::Unmarshal(data, output.bundleName, output.storeId, output.version); -} -} // namespace OHOS::ITypesUtil - \ No newline at end of file diff --git a/relational_store/interfaces/inner_api/cloud_data/include/cloud_service.h b/relational_store/interfaces/inner_api/cloud_data/include/cloud_service.h index a1b69ce2..c180cf99 100644 --- a/relational_store/interfaces/inner_api/cloud_data/include/cloud_service.h +++ b/relational_store/interfaces/inner_api/cloud_data/include/cloud_service.h @@ -55,12 +55,6 @@ public: IPC_PARCEL_ERROR }; - struct RDB_API_EXPORT StoreInfo { - std::string bundleName; - std::string storeId; - int32_t version; - }; - virtual ~CloudService() = default; virtual int32_t EnableCloud(const std::string &id, const std::map &switches) = 0; virtual int32_t DisableCloud(const std::string &id) = 0; -- Gitee From e1809fa9276ea1726d7c3562e28e5360dc205ef9 Mon Sep 17 00:00:00 2001 From: Sven Wang Date: Tue, 25 Apr 2023 11:29:38 +0800 Subject: [PATCH 38/44] update Signed-off-by: Sven Wang --- kv_store/frameworks/common/executor.h | 5 +--- kv_store/frameworks/common/traits.h | 23 ++++++++++++++----- .../communicator/src/protocol_proto.cpp | 2 +- .../src/relational_sync_able_storage.cpp | 2 +- .../src/relational_sync_data_inserter.cpp | 2 +- .../src/relational_sync_data_inserter.h | 2 +- .../storage/src/sqlite/sqlite_utils.cpp | 2 +- .../innerkits/distributeddata/BUILD.gn | 2 +- 8 files changed, 24 insertions(+), 16 deletions(-) diff --git a/kv_store/frameworks/common/executor.h b/kv_store/frameworks/common/executor.h index a9f7be80..91e123e1 100644 --- a/kv_store/frameworks/common/executor.h +++ b/kv_store/frameworks/common/executor.h @@ -41,7 +41,7 @@ public: STOPPED }; struct InnerTask { - std::function exec; + std::function exec = [](InnerTask innerTask) {}; Duration interval = INVALID_INTERVAL; uint64_t times = UNLIMITED_TIMES; TaskId taskId = INVALID_TASK_ID; @@ -98,9 +98,6 @@ private: }); while (running_ == RUNNING && waits_ != nullptr && waits_->Size() > 0) { auto currentTask = waits_->Pop(); - if (!currentTask.Valid()) { - break; - } lock.unlock(); currentTask.exec(currentTask); lock.lock(); diff --git a/kv_store/frameworks/common/traits.h b/kv_store/frameworks/common/traits.h index 08eeb1a4..7f052f86 100644 --- a/kv_store/frameworks/common/traits.h +++ b/kv_store/frameworks/common/traits.h @@ -19,19 +19,21 @@ #include namespace OHOS { namespace Traits { -// same_index_of_v +// If there is one in the ...Types, that is equal to T. same_index_of_v is the index. +// If there is no one in the ...Types, that is equal to T. same_index_of_v is sizeof ...(Types) template inline constexpr size_t same_index_of_v = std::__detail::__variant::__index_of_v; -// same_in_v +// There is one in the ...Types, that is equal to T. If not, the same_in_v will be false. template inline constexpr bool same_in_v = (same_index_of_v < sizeof...(Types)); -// convertible_index_of_v template struct convertible_index_of : std::integral_constant { }; +// If there is one in the ...Types that can convert to T implicitly, convertible_index_v is the index. +// If there is no one in the ...Types that can convert to T implicitly, convertible_index_v is sizeof ...(Types) template inline constexpr size_t convertible_index_v = convertible_index_of<_Tp, _Types...>::value; @@ -40,7 +42,7 @@ struct convertible_index_of<_Tp, _First, _Rest...> : std::integral_constant ? 0 : convertible_index_v<_Tp, _Rest...> + 1> { }; -// convertible_in_v +// There is one in the ...Types, that can convert to T implicitly. If not, the convertible_in_v will be false. template inline constexpr bool convertible_in_v = (convertible_index_v < sizeof...(Types)); @@ -60,12 +62,21 @@ variant_size_of variant_size_test(const std::variant &); template variant_index_of variant_index_test(const T &, const std::variant &); -template -inline constexpr size_t variant_size_of_v = decltype(variant_size_test(std::declval()))::value; +// variant_index_of_v is the count of the variant V's types. +template +inline constexpr size_t variant_size_of_v = decltype(variant_size_test(std::declval()))::value; +// If T is one type of the variant V, variant_index_of_v is the index. If not, variant_index_of_v is the size. template inline constexpr size_t variant_index_of_v = decltype(variant_index_test(std::declval(), std::declval()))::value; +/* + * Extend the template std::get_if(variant<_Types...>*) function to support these: + * 1. When the _Tp is a type in the ..._Types, the get_if is equal to the std::get_if. + * 2. When the _Tp is not a type in the ..._Types but someone in the ...Types can convert to _Tp implicitly, + * the get_if will return it. + * 3. When the _Tp is not a type in the ..._Types and can't convert, the get_if will return nullptr. + * */ template std::enable_if_t, T *> get_if(std::variant *input) { diff --git a/kv_store/frameworks/libs/distributeddb/communicator/src/protocol_proto.cpp b/kv_store/frameworks/libs/distributeddb/communicator/src/protocol_proto.cpp index c7859716..4fce91db 100644 --- a/kv_store/frameworks/libs/distributeddb/communicator/src/protocol_proto.cpp +++ b/kv_store/frameworks/libs/distributeddb/communicator/src/protocol_proto.cpp @@ -15,6 +15,7 @@ #include "protocol_proto.h" #include +#include #include #include "db_common.h" #include "endian_convert.h" @@ -24,7 +25,6 @@ #include "macro_utils.h" #include "securec.h" #include "version.h" -#include namespace DistributedDB { namespace { diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/relational_sync_able_storage.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/relational_sync_able_storage.cpp index 58fb506a..f6587af5 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/relational_sync_able_storage.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/relational_sync_able_storage.cpp @@ -831,7 +831,7 @@ int RelationalSyncAbleStorage::GetRemoteDeviceSchema(const std::string &deviceId if (errCode == -E_NOT_FOUND) { LOGW("Get remote device schema miss cached."); std::string keyStr = DBConstant::REMOTE_DEVICE_SCHEMA_KEY_PREFIX + DBCommon::TransferHashString(deviceId); - Key remoteSchemaKey(keyStr.begin(), keyStr.end());\ + Key remoteSchemaKey(keyStr.begin(), keyStr.end()); Value remoteSchemaBuff; errCode = GetMetaData(remoteSchemaKey, remoteSchemaBuff); if (errCode != E_OK) { diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/relational_sync_data_inserter.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/relational_sync_data_inserter.cpp index 4ca1c35e..07fb3096 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/relational_sync_data_inserter.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/relational_sync_data_inserter.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Huawei Device Co., Ltd. + * 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 diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/relational_sync_data_inserter.h b/kv_store/frameworks/libs/distributeddb/storage/src/relational_sync_data_inserter.h index 714da37f..7120c28a 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/relational_sync_data_inserter.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/relational_sync_data_inserter.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Huawei Device Co., Ltd. + * 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 diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_utils.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_utils.cpp index ec0dac0e..f37ee25a 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_utils.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_utils.cpp @@ -2265,7 +2265,7 @@ int SQLiteUtils::SetKeyInner(sqlite3 *db, CipherType type, const CipherPassword int SQLiteUtils::BindDataValueByType(sqlite3_stmt *statement, const std::optional &data, int cid) { int errCode = E_OK; - StorageType type = data.value().GetType(); + StorageType type = data.value_or(DataValue()).GetType(); switch (type) { case StorageType::STORAGE_TYPE_INTEGER: { int64_t intData = 0; diff --git a/kv_store/interfaces/innerkits/distributeddata/BUILD.gn b/kv_store/interfaces/innerkits/distributeddata/BUILD.gn index b78a26d2..a0ee3aa5 100644 --- a/kv_store/interfaces/innerkits/distributeddata/BUILD.gn +++ b/kv_store/interfaces/innerkits/distributeddata/BUILD.gn @@ -42,7 +42,7 @@ config("distributeddatafwk_config") { } config("distributeddatafwk_public_config") { - visibility = [ "//foundation/distributeddatamgr/kv_store:*" ] + visibility = [ ":*" ] include_dirs = [ "include", -- Gitee From 0daa8dc68e88acb28e8bc55159820b999e4728b4 Mon Sep 17 00:00:00 2001 From: Sven Wang Date: Tue, 25 Apr 2023 20:38:16 +0800 Subject: [PATCH 39/44] update Signed-off-by: Sven Wang --- datamgr_service/conf/config.json | 3 - .../service/test/config_factory_test.cpp | 4 +- .../frameworks/common/test/traits_test.cpp | 250 ++++++++++++++++++ kv_store/frameworks/common/traits.h | 19 +- .../frameworks/native/rdb/include/parser.h | 58 ++++ .../native/rdb/src/abs_shared_result_set.cpp | 10 +- .../frameworks/native/rdb/src/parser.cpp | 48 ++++ .../native/rdb/src/sqlite_statement.cpp | 14 +- .../native/rdb/src/value_object.cpp | 15 -- .../src/rdb_data_ability_utils.cpp | 9 +- .../rdb_data_share_adapter/src/rdb_utils.cpp | 6 +- .../inner_api/rdb/include/asset_value.h | 3 - .../inner_api/rdb/include/value_object.h | 69 ++--- .../include/rdb_data_ability_utils.h | 2 +- .../include/rdb_utils.h | 2 +- .../rdb/unittest/rdb_value_bucket_test.cpp | 30 +-- 16 files changed, 426 insertions(+), 116 deletions(-) create mode 100644 kv_store/frameworks/common/test/traits_test.cpp create mode 100644 relational_store/frameworks/native/rdb/include/parser.h create mode 100644 relational_store/frameworks/native/rdb/src/parser.cpp diff --git a/datamgr_service/conf/config.json b/datamgr_service/conf/config.json index 2bf2041c..1b4ffabc 100644 --- a/datamgr_service/conf/config.json +++ b/datamgr_service/conf/config.json @@ -14,9 +14,6 @@ "count": 1 } }, - { - "lib": "libconfigdemo2.z.so" - }, { "lib": "libudmf_server.z.so" } diff --git a/datamgr_service/services/distributeddataservice/service/test/config_factory_test.cpp b/datamgr_service/services/distributeddataservice/service/test/config_factory_test.cpp index b1ee7541..141f065d 100644 --- a/datamgr_service/services/distributeddataservice/service/test/config_factory_test.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/config_factory_test.cpp @@ -61,7 +61,7 @@ HWTEST_F(ConfigFactoryTest, ComponentConfig, TestSize.Level0) { auto *components = ConfigFactory::GetInstance().GetComponentConfig(); ASSERT_NE(components, nullptr); - ASSERT_EQ(components->size(), 3); + ASSERT_EQ(components->size(), 2); const ComponentConfig &config = (*components)[0]; ASSERT_EQ(config.description, "3rd party adapter"); ASSERT_EQ(config.lib, "libconfigdemo.z.so"); @@ -69,7 +69,7 @@ HWTEST_F(ConfigFactoryTest, ComponentConfig, TestSize.Level0) ASSERT_EQ(config.destructor, ""); ASSERT_EQ(config.params, "{\"count\":1,\"key\":\"value\"}"); const ComponentConfig &cfg = (*components)[1]; - ASSERT_EQ(cfg.lib, "libconfigdemo2.z.so"); + ASSERT_EQ(cfg.lib, "libudmf_server.z.so"); } /** diff --git a/kv_store/frameworks/common/test/traits_test.cpp b/kv_store/frameworks/common/test/traits_test.cpp new file mode 100644 index 00000000..cbf2625a --- /dev/null +++ b/kv_store/frameworks/common/test/traits_test.cpp @@ -0,0 +1,250 @@ +/* + * 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. + */ +#include "traits.h" + +#include +using namespace testing::ext; +namespace OHOS::Test { +class TraitsTest : public testing::Test { +public: + class From { + public: + From() {} + + private: + int64_t id_ = 0; + }; + class Convertible { + public: + Convertible(const From &){}; + Convertible(){} + Convertible(Convertible &&) noexcept {}; + Convertible &operator=(Convertible &&) noexcept + { + return *this; + } + operator From() + { + return From(); + } + private: + int64_t id_ = 1; + }; + static void SetUpTestCase(void){}; + static void TearDownTestCase(void){}; + void SetUp(){}; + void TearDown() {} +}; + +/** +* @tc.name: same_index_of_v +* @tc.desc: +* @tc.type: FUNC +* @tc.require: +* @tc.author: Sven Wang +*/ +HWTEST_F(TraitsTest, same_index_of_v, TestSize.Level0) +{ + auto index = Traits::same_index_of_v>; + ASSERT_EQ(index, 0); + index = Traits::same_index_of_v>; + ASSERT_EQ(index, 3); + index = Traits::same_index_of_v; + ASSERT_EQ(index, 0); +} + +/** +* @tc.name: same_in_v +* @tc.desc: +* @tc.type: FUNC +* @tc.require: +* @tc.author: Sven Wang +*/ +HWTEST_F(TraitsTest, same_in_v, TestSize.Level0) +{ + auto exist = Traits::same_in_v>; + ASSERT_TRUE(exist); + exist = Traits::same_in_v>; + ASSERT_FALSE(exist); + exist = Traits::same_in_v; + ASSERT_FALSE(exist); +} + +/** +* @tc.name: convertible_index_of_v +* @tc.desc: +* @tc.type: FUNC +* @tc.require: +* @tc.author: Sven Wang +*/ +HWTEST_F(TraitsTest, convertible_index_of_v, TestSize.Level0) +{ + auto index = Traits::convertible_index_of_v>; + ASSERT_EQ(index, 0); + index = Traits::convertible_index_of_v>; + ASSERT_EQ(index, 1); + index = Traits::convertible_index_of_v>; + ASSERT_EQ(index, 2); + index = Traits::convertible_index_of_v; + ASSERT_EQ(index, 0); +} + +/** +* @tc.name: convertible_in_v +* @tc.desc: +* @tc.type: FUNC +* @tc.require: +* @tc.author: Sven Wang +*/ +HWTEST_F(TraitsTest, convertible_in_v, TestSize.Level0) +{ + auto convertible = Traits::convertible_in_v>; + ASSERT_TRUE(convertible); + convertible = Traits::convertible_in_v>; + ASSERT_TRUE(convertible); + convertible = Traits::convertible_in_v>; + ASSERT_FALSE(convertible); + convertible = Traits::convertible_in_v; + ASSERT_FALSE(convertible); +} + +/** +* @tc.name: variant_size_of_v +* @tc.desc: +* @tc.type: FUNC +* @tc.require: +* @tc.author: Sven Wang +*/ +HWTEST_F(TraitsTest, variant_size_of_v, TestSize.Level0) +{ + std::variant> value; + auto size = Traits::variant_size_of_v; + ASSERT_EQ(size, 6); + std::variant value2; + size = Traits::variant_size_of_v; + ASSERT_EQ(size, 1); +} + +/** +* @tc.name: variant_index_of_v +* @tc.desc: +* @tc.type: FUNC +* @tc.require: +* @tc.author: Sven Wang +*/ +HWTEST_F(TraitsTest, variant_index_of_v, TestSize.Level0) +{ + std::variant> value; + auto index = Traits::variant_index_of_v; + ASSERT_EQ(index, 0); + index = Traits::variant_index_of_v; + ASSERT_EQ(index, 1); + index = Traits::variant_index_of_v; + ASSERT_EQ(index, 2); + index = Traits::variant_index_of_v; + ASSERT_EQ(index, 3); + index = Traits::variant_index_of_v; + ASSERT_EQ(index, 4); + index = Traits::variant_index_of_v, decltype(value)>; + ASSERT_EQ(index, 5); + index = Traits::variant_index_of_v; + ASSERT_EQ(index, 6); +} + +/** +* @tc.name: get_if_same_type +* @tc.desc: +* @tc.type: FUNC +* @tc.require: +* @tc.author: Sven Wang +*/ +HWTEST_F(TraitsTest, get_if_same_type, TestSize.Level0) +{ + // 1. When the _Tp is a type in the ..._Types, the get_if is equal to the std::get_if. + std::variant value; + auto *nil = Traits::get_if(&value); + ASSERT_NE(nil, nullptr); + auto *number = Traits::get_if(&value); + ASSERT_EQ(number, nullptr); + value = int64_t(1); + number = Traits::get_if(&value); + ASSERT_NE(number, nullptr); + ASSERT_EQ(*number, 1); + value = 1.5; + auto *dVal = Traits::get_if(&value); + ASSERT_NE(dVal, nullptr); + ASSERT_DOUBLE_EQ(*dVal, 1.5); + value = "test case"; + auto *charPtr = Traits::get_if(&value); + ASSERT_NE(charPtr, nullptr); + ASSERT_TRUE(strcmp(*charPtr, "test case") == 0); +} +/** +* @tc.name: get_if_convertible_type +* @tc.desc: +* @tc.type: FUNC +* @tc.require: +* @tc.author: Sven Wang +*/ +HWTEST_F(TraitsTest, get_if_convertible_type, TestSize.Level0) +{ + // 2. When the _Tp is not a type in the ..._Types but someone in the ...Types can convert to _Tp implicitly, + // the get_if will return it. + std::variant value; + value = int64_t(1); + auto *fVal = Traits::get_if(&value); + static_assert(std::is_same_v, "int64_t convert to float implicitly!"); + ASSERT_NE(fVal, nullptr); + ASSERT_EQ(*fVal, 1); + + value = "test case"; + auto *strVal = Traits::get_if(&value); + ASSERT_NE(strVal, nullptr); + ASSERT_TRUE(strcmp(*strVal, "test case") == 0); + + value = From(); + auto *toVal = Traits::get_if(&value); + ASSERT_NE(toVal, nullptr); + + std::variant val2; + val2 = Convertible(); + auto *fromVal = Traits::get_if(&val2); + ASSERT_NE(fromVal, nullptr); +} + +/** +* @tc.name: get_if_invalid_type +* @tc.desc: +* @tc.type: FUNC +* @tc.require: +* @tc.author: Sven Wang +*/ +HWTEST_F(TraitsTest, get_if_invalid_type, TestSize.Level0) +{ + // 3. When the _Tp is not a type in the ..._Types and can't convert, the get_if will return nullptr. + std::variant value; + auto *unknown = Traits::get_if>(&value); + ASSERT_EQ(unknown, nullptr); + value = int64_t(9); + unknown = Traits::get_if>(&value); + ASSERT_EQ(unknown, nullptr); + value = 1.5; + unknown = Traits::get_if>(&value); + ASSERT_EQ(unknown, nullptr); + value = "test case"; + unknown = Traits::get_if>(&value); + ASSERT_EQ(unknown, nullptr); +} +} // namespace OHOS::Test diff --git a/kv_store/frameworks/common/traits.h b/kv_store/frameworks/common/traits.h index 7f052f86..3a4c0023 100644 --- a/kv_store/frameworks/common/traits.h +++ b/kv_store/frameworks/common/traits.h @@ -15,6 +15,7 @@ #ifndef OHOS_DISTRIBUTED_DATA_FRAMEWORKS_COMMON_TRAITS_H #define OHOS_DISTRIBUTED_DATA_FRAMEWORKS_COMMON_TRAITS_H +#include #include #include namespace OHOS { @@ -28,23 +29,23 @@ inline constexpr size_t same_index_of_v = std::__detail::__variant::__index_of_v template inline constexpr bool same_in_v = (same_index_of_v < sizeof...(Types)); -template +template struct convertible_index_of : std::integral_constant { }; // If there is one in the ...Types that can convert to T implicitly, convertible_index_v is the index. // If there is no one in the ...Types that can convert to T implicitly, convertible_index_v is sizeof ...(Types) -template -inline constexpr size_t convertible_index_v = convertible_index_of<_Tp, _Types...>::value; +template +inline constexpr size_t convertible_index_of_v = convertible_index_of::value; -template -struct convertible_index_of<_Tp, _First, _Rest...> - : std::integral_constant ? 0 : convertible_index_v<_Tp, _Rest...> + 1> { +template +struct convertible_index_of + : std::integral_constant ? 0 : convertible_index_of_v + 1> { }; // There is one in the ...Types, that can convert to T implicitly. If not, the convertible_in_v will be false. template -inline constexpr bool convertible_in_v = (convertible_index_v < sizeof...(Types)); +inline constexpr bool convertible_in_v = (convertible_index_of_v < sizeof...(Types)); template struct variant_size_of { @@ -89,7 +90,7 @@ std::enable_if_t, const T *> get_if(const std::variant(input); } -template ? convertible_index_v : 0> +template ? convertible_index_of_v : 0> constexpr std::enable_if_t && convertible_in_v, std::add_pointer_t>>> get_if(std::variant *input) @@ -97,7 +98,7 @@ get_if(std::variant *input) return std::get_if(input); } -template ? convertible_index_v : 0> +template ? convertible_index_of_v : 0> constexpr std::enable_if_t && convertible_in_v, std::add_pointer_t>>> get_if(const std::variant *input) diff --git a/relational_store/frameworks/native/rdb/include/parser.h b/relational_store/frameworks/native/rdb/include/parser.h new file mode 100644 index 00000000..906815fe --- /dev/null +++ b/relational_store/frameworks/native/rdb/include/parser.h @@ -0,0 +1,58 @@ +/* + * 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_DISTRIBUTED_DATA_RELATIONAL_STORE_FRAMEWORKS_NATIVE_RDB_PARSER_H +#define OHOS_DISTRIBUTED_DATA_RELATIONAL_STORE_FRAMEWORKS_NATIVE_RDB_PARSER_H +#include "traits.h" +#include "value_object.h" +namespace OHOS::NativeRdb { +class Parser final { +public: + using Asset = ValueObject::Asset; + using Assets = ValueObject::Assets; + template + static bool Convert(T input, std::variant &output); + static size_t ParserRawData(const uint8_t *data, size_t length, Asset &asset); + static size_t ParserRawData(const uint8_t *data, size_t length, Assets &assets); + static std::vector PackageRawData(const Asset &asset); + static std::vector PackageRawData(const Assets &assets); + +private: + template + static bool Get(T &&input, O &output) + { + return false; + } + + template + static bool Get(T &&input, O &output) + { + auto *val = Traits::get_if(&input); + if (val != nullptr) { + output = std::move(*val); + return true; + } + return Get(std::move(input), output); + } +}; + +template +bool Parser::Convert(T input, std::variant &output) +{ + return Get(std::move(input), output); +} +} + +#endif // OHOS_DISTRIBUTED_DATA_RELATIONAL_STORE_FRAMEWORKS_NATIVE_RDB_PARSER_H diff --git a/relational_store/frameworks/native/rdb/src/abs_shared_result_set.cpp b/relational_store/frameworks/native/rdb/src/abs_shared_result_set.cpp index 2e2ead4f..6483d8c3 100644 --- a/relational_store/frameworks/native/rdb/src/abs_shared_result_set.cpp +++ b/relational_store/frameworks/native/rdb/src/abs_shared_result_set.cpp @@ -23,6 +23,7 @@ #include "logger.h" #include "parcel.h" +#include "parser.h" #include "rdb_errno.h" #include "rdb_trace.h" #include "shared_block.h" @@ -338,7 +339,7 @@ int AbsSharedResultSet::GetAsset(int32_t col, ValueObject::Asset &value) size_t size = 0; auto data = reinterpret_cast(sharedBlock_->GetCellUnitValueBlob(cellUnit, &size)); ValueObject::Asset asset; - ValueObject::FromRawData(data, size, asset); + Parser::ParserRawData(data, size, asset); value = std::move(asset); return E_OK; } @@ -364,13 +365,8 @@ int AbsSharedResultSet::GetAssets(int32_t col, ValueObject::Assets &value) size_t size = 0; auto data = reinterpret_cast(sharedBlock_->GetCellUnitValueBlob(cellUnit, &size)); - size_t offset = 0; ValueObject::Assets assets; - while (offset < size) { - ValueObject::Asset asset; - offset += ValueObject::FromRawData(&data[offset], size, asset); - assets.push_back(std::move(asset)); - } + Parser::ParserRawData(data, size, assets); value = std::move(assets); return E_OK; } diff --git a/relational_store/frameworks/native/rdb/src/parser.cpp b/relational_store/frameworks/native/rdb/src/parser.cpp new file mode 100644 index 00000000..d86fd27f --- /dev/null +++ b/relational_store/frameworks/native/rdb/src/parser.cpp @@ -0,0 +1,48 @@ +/* + * 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. + */ + +#include "parser.h" +#include "value_object.h" +#include "securec.h" +namespace OHOS::NativeRdb { +size_t Parser::ParserRawData(const uint8_t *data, size_t length, Asset &asset) +{ + size_t used = 0; + uint16_t type = ValueObject::TYPE_INDEX; + if (used + sizeof(type) > length) { + return used; + } + memcpy_s(&asset.version, sizeof(asset.version), data, length); + asset.version = le32toh(asset.version); + used += sizeof(asset.version); + return sizeof(asset.version); +} +size_t Parser::ParserRawData(const uint8_t *data, size_t length, Assets &assets) +{ + uint16_t num = 0; + return 0; +} +std::vector Parser::PackageRawData(const Asset &asset) +{ + std::vector rawData; + uint32_t version = htole32(asset.version); + rawData.assign(reinterpret_cast(&version), reinterpret_cast(&version) + sizeof(version)); + return rawData; +} +std::vector Parser::PackageRawData(const Assets &assets) +{ + return std::vector(); +} +} // namespace OHOS::NativeRdb \ No newline at end of file diff --git a/relational_store/frameworks/native/rdb/src/sqlite_statement.cpp b/relational_store/frameworks/native/rdb/src/sqlite_statement.cpp index a8dd2f52..31ace28f 100644 --- a/relational_store/frameworks/native/rdb/src/sqlite_statement.cpp +++ b/relational_store/frameworks/native/rdb/src/sqlite_statement.cpp @@ -15,10 +15,11 @@ #include "sqlite_statement.h" -#include #include +#include #include "logger.h" +#include "parser.h" #include "rdb_errno.h" #include "sqlite_errno.h" @@ -430,18 +431,13 @@ int SqliteStatement::GetColumn(int index, ValueObject &value) const std::string declType = decl; if (declType == ValueObject::DeclType()) { Asset asset; - (void)ValueObject::FromRawData(blob, size, asset); - value = asset; + Parser::ParserRawData(blob, size, asset); + value = std::move(asset); return E_OK; } if (declType == ValueObject::DeclType()) { - size_t offset = 0; Assets assets; - while (offset < size) { - Asset asset; - offset += ValueObject::FromRawData(&blob[offset], size - offset, asset); - assets.push_back(std::move(asset)); - } + Parser::ParserRawData(blob, size, assets); value = std::move(assets); return E_OK; } diff --git a/relational_store/frameworks/native/rdb/src/value_object.cpp b/relational_store/frameworks/native/rdb/src/value_object.cpp index e13203a2..ebc50536 100644 --- a/relational_store/frameworks/native/rdb/src/value_object.cpp +++ b/relational_store/frameworks/native/rdb/src/value_object.cpp @@ -162,20 +162,5 @@ int ValueObject::Get(T &output) const output = static_cast(*v); return E_OK; } - -std::vector ValueObject::ToRawData(Asset &asset) -{ - std::vector rawData; - uint32_t version = htole32(asset.version); - rawData.assign(reinterpret_cast(&version), reinterpret_cast(&version) + sizeof(version)); - return rawData; -} - -size_t ValueObject::FromRawData(const uint8_t *rawData, size_t length, Asset &asset) -{ - memcpy_s(&asset.version, sizeof(asset.version), rawData, length); - asset.version = le32toh(asset.version); - return sizeof(asset.version); -} } // namespace NativeRdb } // namespace OHOS diff --git a/relational_store/frameworks/native/rdb_data_ability_adapter/src/rdb_data_ability_utils.cpp b/relational_store/frameworks/native/rdb_data_ability_adapter/src/rdb_data_ability_utils.cpp index 7cf48ca4..082ebe53 100644 --- a/relational_store/frameworks/native/rdb_data_ability_adapter/src/rdb_data_ability_utils.cpp +++ b/relational_store/frameworks/native/rdb_data_ability_adapter/src/rdb_data_ability_utils.cpp @@ -14,8 +14,9 @@ */ #include "rdb_data_ability_utils.h" -#include "result_set_utils.h" +#include "parser.h" +#include "result_set_utils.h" using namespace OHOS::RdbDataAbilityAdapter; using namespace OHOS::DataShare; using namespace OHOS::NativeRdb; @@ -28,13 +29,13 @@ RdbDataAbilityUtils::~RdbDataAbilityUtils() { } -DataShareValuesBucket RdbDataAbilityUtils::ToDataShareValuesBucket(const ValuesBucket &valuesBucket) +DataShareValuesBucket RdbDataAbilityUtils::ToDataShareValuesBucket(ValuesBucket valuesBucket) { std::map values; for (auto &[key, value] : valuesBucket.values_) { DataShareValueObject::Type dsValue; - ValueObject::Convert(value.value, dsValue); - values.insert(std::make_pair(key, dsValue)); + Parser::Convert(std::move(value.value), dsValue); + values.insert(std::make_pair(key, std::move(dsValue))); } return DataShareValuesBucket(std::move(values)); } diff --git a/relational_store/frameworks/native/rdb_data_share_adapter/src/rdb_utils.cpp b/relational_store/frameworks/native/rdb_data_share_adapter/src/rdb_utils.cpp index 46fbe83e..bac02d0a 100644 --- a/relational_store/frameworks/native/rdb_data_share_adapter/src/rdb_utils.cpp +++ b/relational_store/frameworks/native/rdb_data_share_adapter/src/rdb_utils.cpp @@ -15,20 +15,20 @@ #include "rdb_utils.h" +#include "parser.h" #include "rdb_logger.h" - using namespace OHOS::RdbDataShareAdapter; using namespace OHOS::DataShare; using namespace OHOS::NativeRdb; constexpr RdbUtils::OperateHandler RdbUtils::HANDLERS[LAST_TYPE]; -ValuesBucket RdbUtils::ToValuesBucket(const DataShareValuesBucket &valuesBucket) +ValuesBucket RdbUtils::ToValuesBucket(DataShareValuesBucket valuesBucket) { std::map valuesMap; for (auto &[key, dsValue] : valuesBucket.valuesMap) { ValueObject::Type value; - ValueObject::Convert(dsValue, value); + Parser::Convert(std::move(dsValue), value); valuesMap.insert(std::pair(key, std::move(value))); } return ValuesBucket(valuesMap); diff --git a/relational_store/interfaces/inner_api/rdb/include/asset_value.h b/relational_store/interfaces/inner_api/rdb/include/asset_value.h index e898bdd3..ad891c37 100644 --- a/relational_store/interfaces/inner_api/rdb/include/asset_value.h +++ b/relational_store/interfaces/inner_api/rdb/include/asset_value.h @@ -26,9 +26,6 @@ struct AssetValue { std::string modifyTime; std::string size; std::string hash; - - std::vector ToRawData(); - size_t FromRawData(const uint8_t *rawData, size_t size); }; } #endif // OHOS_RELATIONAL_STORE_INNER_API_ASSET_VALUE_H diff --git a/relational_store/interfaces/inner_api/rdb/include/value_object.h b/relational_store/interfaces/inner_api/rdb/include/value_object.h index c407b3a2..d9bf97db 100644 --- a/relational_store/interfaces/inner_api/rdb/include/value_object.h +++ b/relational_store/interfaces/inner_api/rdb/include/value_object.h @@ -22,7 +22,6 @@ #include "asset_value.h" #include "rdb_visibility.h" -#include "traits.h" namespace OHOS { namespace NativeRdb { /** @@ -39,17 +38,34 @@ public: using Assets = std::vector; using Type = std::variant; - template - inline constexpr static size_t TYPE_INDEX = Traits::variant_index_of_v; + template + struct variant_size_of { + static constexpr size_t value = sizeof...(Types); + }; + + template + struct variant_index_of { + static constexpr size_t value = std::__detail::__variant::__index_of_v; + }; + + template + static variant_size_of variant_size_test(const std::variant &); + + template + static variant_index_of variant_index_test(const T &, const std::variant &); - inline constexpr static size_t TYPE_MAX = Traits::variant_size_of_v; + template + inline constexpr static int32_t TYPE_INDEX = + decltype(variant_index_test(std::declval(), std::declval()))::value; + + inline constexpr static int32_t TYPE_MAX = decltype(variant_size_test(std::declval()))::value; /** * @brief Indicates the ValueObject {@link ValueObject} type. * */ enum TypeId : int32_t { /** Indicates the ValueObject type is NULL.*/ - TYPE_NULL = TYPE_INDEX, + TYPE_NULL = TYPE_INDEX, /** Indicates the ValueObject type is int.*/ TYPE_INT = TYPE_INDEX, /** Indicates the ValueObject type is double.*/ @@ -64,29 +80,18 @@ public: TYPE_ASSET = TYPE_INDEX, /** Indicates the ValueObject type is assets.*/ TYPE_ASSETS = TYPE_INDEX, - TYPE_BUTT + /** the BUTT.*/ + TYPE_BUTT = TYPE_MAX }; Type value; - /** - * @brief convert a std::variant input to another std::variant output with different (..._Types) - */ - template - static bool Convert(const _T &input, std::variant<_Rest...> &output); - - /** - * @brief convert a std::variant input to another std::variant output with different (..._Types) - */ - static std::vector ToRawData(Asset &asset); - static size_t FromRawData(const uint8_t *rawData, size_t length, Asset &asset); - /** * @brief convert a std::variant input to another std::variant output with different (..._Types) */ template - static inline std::enable_if_t < TYPE_INDEX DeclType() + static inline std::enable_if_t< (TYPE_INDEX) < TYPE_MAX, const char *> DeclType() { - return DECLARE_TYPES[Traits::variant_index_of_v]; + return DECLARE_TYPES[TYPE_INDEX]; } /** * @brief Constructor. @@ -323,24 +328,6 @@ public: private: template int Get(T &output) const; - - template - static bool Get(const _T &input, _O &output) - { - return false; - } - - template - static bool Get(const _T &input, _O &output) - { - const auto *val = Traits::get_if<_First>(&input); - if (val != nullptr) { - output = *val; - return true; - } - return Get<_T, _O, _Rest...>(input, output); - } - static constexpr const char *DECLARE_TYPES[TypeId::TYPE_BUTT] = { /** Indicates the ValueObject type is NULL.*/ "", @@ -360,12 +347,6 @@ private: "ASSETS" }; }; - -template -bool ValueObject::Convert(const _T &input, std::variant<_Rest...> &output) -{ - return Get<_T, decltype(output), _Rest...>(input, output); -} using ValueObjectType = ValueObject::TypeId; } // namespace NativeRdb } // namespace OHOS diff --git a/relational_store/interfaces/inner_api/rdb_data_ability_adapter/include/rdb_data_ability_utils.h b/relational_store/interfaces/inner_api/rdb_data_ability_adapter/include/rdb_data_ability_utils.h index 2987783f..5aef2bd6 100644 --- a/relational_store/interfaces/inner_api/rdb_data_ability_adapter/include/rdb_data_ability_utils.h +++ b/relational_store/interfaces/inner_api/rdb_data_ability_adapter/include/rdb_data_ability_utils.h @@ -73,7 +73,7 @@ public: /** * @brief Convert NativeRdb::ValuesBucket to DataShare::DataShareValuesBucket. */ - RDB_API_EXPORT static DataShareValuesBucket ToDataShareValuesBucket(const ValuesBucket &valuesBucket); + RDB_API_EXPORT static DataShareValuesBucket ToDataShareValuesBucket(ValuesBucket valuesBucket); /** * @brief Convert NativeRdb::DataAbilityPredicates to DataShare::DataSharePredicates. diff --git a/relational_store/interfaces/inner_api/rdb_data_share_adapter/include/rdb_utils.h b/relational_store/interfaces/inner_api/rdb_data_share_adapter/include/rdb_utils.h index 04a1ed11..f5ecd9a9 100644 --- a/relational_store/interfaces/inner_api/rdb_data_share_adapter/include/rdb_utils.h +++ b/relational_store/interfaces/inner_api/rdb_data_share_adapter/include/rdb_utils.h @@ -81,7 +81,7 @@ public: /** * @brief Convert DataShare::DataShareValuesBucket to NativeRdb::ValuesBucket. */ - RDB_API_EXPORT static ValuesBucket ToValuesBucket(const DataShareValuesBucket &bucket); + RDB_API_EXPORT static ValuesBucket ToValuesBucket(DataShareValuesBucket bucket); /** * @brief Convert DataShare::DataShareAbsPredicates to NativeRdb::RdbPredicates. diff --git a/relational_store/test/native/rdb/unittest/rdb_value_bucket_test.cpp b/relational_store/test/native/rdb/unittest/rdb_value_bucket_test.cpp index 3c69815d..f295f31d 100644 --- a/relational_store/test/native/rdb/unittest/rdb_value_bucket_test.cpp +++ b/relational_store/test/native/rdb/unittest/rdb_value_bucket_test.cpp @@ -14,16 +14,16 @@ */ #include - #include +#include "itypes_util.h" #include "logger.h" #include "message_parcel.h" #include "parcel.h" +#include "parser.h" +#include "sqlite_global_config.h" #include "value_object.h" #include "values_bucket.h" -#include "sqlite_global_config.h" -#include "itypes_util.h" using namespace testing::ext; using namespace OHOS; using namespace OHOS::NativeRdb; @@ -247,25 +247,25 @@ HWTEST_F(ValuesBucketTest, Convert_From_Subset, TestSize.Level1) ValueObject::Type output = AssetValue(); using Type = std::variant>; Type input; - ValueObject::Convert(input, output); + Parser::Convert(input, output); auto *nil = std::get_if(&output); EXPECT_TRUE(nil != nullptr); input = int64_t(54); - ValueObject::Convert(input, output); + Parser::Convert(input, output); auto *number = std::get_if(&output); EXPECT_TRUE(number != nullptr); EXPECT_TRUE(*number == 54); input = double(1.1); - ValueObject::Convert(input, output); + Parser::Convert(input, output); auto *real = std::get_if(&output); EXPECT_TRUE(real != nullptr); input = std::string("my test"); - ValueObject::Convert(input, output); + Parser::Convert(input, output); auto *text = std::get_if(&output); EXPECT_TRUE(text != nullptr); EXPECT_TRUE(*text == "my test"); input = std::vector(10, 'm'); - ValueObject::Convert(input, output); + Parser::Convert(input, output); auto *blob = std::get_if>(&output); EXPECT_TRUE(blob != nullptr); EXPECT_TRUE(*blob == std::vector(10, 'm')); @@ -281,37 +281,37 @@ HWTEST_F(ValuesBucketTest, Convert_To_Subset, TestSize.Level1) using Type = std::variant>; Type output; ValueObject::Type input; - ValueObject::Convert(input, output); + Parser::Convert(input, output); auto *nil = std::get_if(&output); EXPECT_TRUE(nil != nullptr); input = int64_t(54); - ValueObject::Convert(input, output); + Parser::Convert(input, output); auto *number = std::get_if(&output); EXPECT_TRUE(number != nullptr); EXPECT_TRUE(*number == 54); input = double(1.1); - ValueObject::Convert(input, output); + Parser::Convert(input, output); auto *real = std::get_if(&output); EXPECT_TRUE(real != nullptr); input = std::string("my test"); - ValueObject::Convert(input, output); + Parser::Convert(input, output); auto *text = std::get_if(&output); EXPECT_TRUE(text != nullptr); EXPECT_TRUE(*text == "my test"); input = std::vector(10, 'm'); - ValueObject::Convert(input, output); + Parser::Convert(input, output); auto *blob = std::get_if>(&output); EXPECT_TRUE(blob != nullptr); EXPECT_TRUE(*blob == std::vector(10, 'm')); AssetValue value{.version = 0, .name = "123", .uri = "my test path", .createTime = "12", .modifyTime = "12"}; input = value ; output = {}; - ValueObject::Convert(input, output); + Parser::Convert(input, output); nil = std::get_if(&output); EXPECT_TRUE(nil != nullptr); input = std::vector(10, value); output = {}; - ValueObject::Convert(input, output); + Parser::Convert(input, output); nil = std::get_if(&output); EXPECT_TRUE(nil != nullptr); } \ No newline at end of file -- Gitee From 2a1dae39f0b7f49a401f72c29be302693e2b414e Mon Sep 17 00:00:00 2001 From: Sven Wang Date: Wed, 26 Apr 2023 10:51:50 +0800 Subject: [PATCH 40/44] update Signed-off-by: Sven Wang --- .../framework/cloud/asset_loader.cpp | 11 +++ .../framework/cloud/cloud_db.cpp | 86 +++++++++++++++++++ .../framework/cloud/cloud_server.cpp | 4 +- .../framework/include/cloud/asset_loader.h | 7 +- .../framework/include/cloud/cloud_db.h | 39 ++++++--- .../framework/include/cloud/cloud_server.h | 10 +-- .../framework/include/store/auto_cache.h | 28 +++--- .../framework/include/store/general_store.h | 14 ++- .../framework/include/store/general_watcher.h | 4 +- .../service/rdb/rdb_general_store.cpp | 22 ++--- .../service/rdb/rdb_general_store.h | 5 +- 11 files changed, 172 insertions(+), 58 deletions(-) diff --git a/datamgr_service/services/distributeddataservice/framework/cloud/asset_loader.cpp b/datamgr_service/services/distributeddataservice/framework/cloud/asset_loader.cpp index adbf4f08..cef89e7d 100644 --- a/datamgr_service/services/distributeddataservice/framework/cloud/asset_loader.cpp +++ b/datamgr_service/services/distributeddataservice/framework/cloud/asset_loader.cpp @@ -14,3 +14,14 @@ */ #include "cloud/asset_loader.h" +namespace OHOS::DistributedData { +int32_t AssetLoader::Upload(const std::vector &assets) +{ + return E_NOT_SUPPORT; +} + +int32_t AssetLoader::Download(std::vector &assets) +{ + return E_NOT_SUPPORT; +} +} diff --git a/datamgr_service/services/distributeddataservice/framework/cloud/cloud_db.cpp b/datamgr_service/services/distributeddataservice/framework/cloud/cloud_db.cpp index 65bb7b3e..058bdab9 100644 --- a/datamgr_service/services/distributeddataservice/framework/cloud/cloud_db.cpp +++ b/datamgr_service/services/distributeddataservice/framework/cloud/cloud_db.cpp @@ -14,3 +14,89 @@ */ #include "cloud/cloud_db.h" +namespace OHOS::DistributedData { +int32_t CloudDB::Close() +{ + return E_NOT_SUPPORT; +} + +int32_t CloudDB::Execute(const std::string &table, const std::string &sql) +{ + return E_NOT_SUPPORT; +} + +int32_t CloudDB::BatchInsert(const std::string &table, VBuckets &&values) +{ + return E_NOT_SUPPORT; +} + +int32_t CloudDB::BatchUpdate(const std::string &table, const std::string &sql, VBuckets &&values) +{ + return E_NOT_SUPPORT; +} + +int32_t CloudDB::Delete(const std::string &table, const std::string &sql, Values &&args) +{ + return E_NOT_SUPPORT; +} + +std::shared_ptr CloudDB::Query(const std::string &table, const std::string &sql, Values &&args) +{ + return nullptr; +} + +int32_t CloudDB::Sync(const Devices &devices, int32_t mode, const GenQuery &query, Async async, int32_t wait) +{ + return E_NOT_SUPPORT; +} + +int32_t CloudDB::Watch(int32_t origin, Watcher &watcher) +{ + return E_NOT_SUPPORT; +} + +int32_t CloudDB::Unwatch(int32_t origin, Watcher &watcher) +{ + return E_NOT_SUPPORT; +} + +int32_t CloudDB::Execute(const std::string &table, const std::string &sql, const VBucket &extend) +{ + return E_NOT_SUPPORT; +} + +int32_t CloudDB::BatchInsert(const std::string &table, VBuckets &&values, VBuckets &extends) +{ + return E_NOT_SUPPORT; +} + +int32_t CloudDB::BatchUpdate(const std::string &table, VBuckets &&values, const VBuckets &extends) +{ + return E_NOT_SUPPORT; +} + +int32_t CloudDB::BatchDelete(const std::string &table, const VBuckets &extends) +{ + return E_NOT_SUPPORT; +} + +std::shared_ptr CloudDB::Query(const std::string &table, const VBucket &extend) +{ + return nullptr; +} + +int32_t CloudDB::Lock() +{ + return E_NOT_SUPPORT; +} + +int32_t CloudDB::Heartbeat() +{ + return E_NOT_SUPPORT; +} + +int32_t CloudDB::Unlock() +{ + return E_NOT_SUPPORT; +} +} // namespace OHOS::DistributedData diff --git a/datamgr_service/services/distributeddataservice/framework/cloud/cloud_server.cpp b/datamgr_service/services/distributeddataservice/framework/cloud/cloud_server.cpp index 036a7229..a2e0f716 100644 --- a/datamgr_service/services/distributeddataservice/framework/cloud/cloud_server.cpp +++ b/datamgr_service/services/distributeddataservice/framework/cloud/cloud_server.cpp @@ -42,11 +42,11 @@ SchemaMeta CloudServer::GetAppSchema(int32_t userId, const std::string &bundleNa std::shared_ptr CloudServer::ConnectAssetLoader(uint32_t tokenId, const CloudServer::Database &dbMeta) { - return std::shared_ptr(); + return nullptr; } std::shared_ptr CloudServer::ConnectCloudDB(uint32_t tokenId, const CloudServer::Database &dbMeta) { - return std::shared_ptr(); + return nullptr; } } // namespace OHOS::DistributedData \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/framework/include/cloud/asset_loader.h b/datamgr_service/services/distributeddataservice/framework/include/cloud/asset_loader.h index 8e43f360..0df69eb0 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/cloud/asset_loader.h +++ b/datamgr_service/services/distributeddataservice/framework/include/cloud/asset_loader.h @@ -16,12 +16,13 @@ #define OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_CLOUD_ASSET_LOADER_H #include #include "store/general_value.h" +#include "visibility.h" namespace OHOS::DistributedData { -class AssetLoader { +class API_EXPORT AssetLoader { public: virtual ~AssetLoader() = default; - virtual int32_t Upload(const std::vector &assets) = 0; - virtual int32_t Download(std::vector &assets) = 0; + virtual int32_t Upload(const std::vector &assets); + virtual int32_t Download(std::vector &assets); }; } // namespace OHOS::DistributedData #endif // OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_CLOUD_ASSET_LOADER_H diff --git a/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_db.h b/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_db.h index 5b968212..7f8caa66 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_db.h +++ b/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_db.h @@ -16,20 +16,35 @@ #ifndef OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_CLOUD_CLOUD_DB_H #define OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_CLOUD_CLOUD_DB_H #include "store/general_store.h" +#include "visibility.h" namespace OHOS::DistributedData { -class CloudDB : public GeneralStore { +class API_EXPORT CloudDB : public GeneralStore { public: - virtual int32_t Execute(const std::string &table, const std::string &sql, const VBucket &extend) = 0; - virtual int32_t Insert(const std::string &table, VBucket &&values, VBucket &extend) = 0; - virtual int32_t BatchInsert(const std::string &table, VBuckets &&values, VBuckets &extends) = 0; - virtual int32_t Update(const std::string &table, VBucket &&values, const VBucket &extend) = 0; - virtual int32_t BatchUpdate(const std::string &table, VBuckets &&values, const VBuckets &extends) = 0; - virtual int32_t Delete(const std::string &table, const VBucket &extend) = 0; - virtual int32_t BatchDelete(const std::string &table, const VBuckets &extends) = 0; - virtual std::shared_ptr Query(const std::string &table, const VBucket &extend) = 0; - virtual int32_t Lock() = 0; - virtual int32_t Unlock() = 0; - virtual int32_t Flush() = 0; + int32_t Close() override; + int32_t Execute(const std::string &table, const std::string &sql) override; + int32_t BatchInsert(const std::string &table, VBuckets &&values) override; + int32_t BatchUpdate(const std::string &table, const std::string &sql, VBuckets &&values) override; + int32_t Delete(const std::string &table, const std::string &sql, Values &&args) override; + std::shared_ptr Query(const std::string &table, const std::string &sql, Values &&args) override; + int32_t Sync(const Devices &devices, int32_t mode, const GenQuery &query, Async async, int32_t wait) override; + int32_t Watch(int32_t origin, Watcher &watcher) override; + int32_t Unwatch(int32_t origin, Watcher &watcher) override; + + virtual int32_t Execute(const std::string &table, const std::string &sql, const VBucket &extend); + + virtual int32_t BatchInsert(const std::string &table, VBuckets &&values, VBuckets &extends); + + virtual int32_t BatchUpdate(const std::string &table, VBuckets &&values, const VBuckets &extends); + + virtual int32_t BatchDelete(const std::string &table, const VBuckets &extends); + + virtual std::shared_ptr Query(const std::string &table, const VBucket &extend); + + virtual int32_t Lock(); + + virtual int32_t Heartbeat(); + + virtual int32_t Unlock(); }; } // namespace OHOS::DistributedData #endif // OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_CLOUD_CLOUD_DB_H diff --git a/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_server.h b/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_server.h index d055c675..eee93713 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_server.h +++ b/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_server.h @@ -21,16 +21,16 @@ #include "cloud/schema_meta.h" #include "visibility.h" namespace OHOS::DistributedData { -class CloudServer { +class API_EXPORT CloudServer { public: using Database = SchemaMeta::Database; API_EXPORT static CloudServer *GetInstance(); API_EXPORT static bool RegisterCloudInstance(CloudServer *instance); - virtual CloudInfo GetServerInfo(int32_t userId) = 0; - virtual SchemaMeta GetAppSchema(int32_t userId, const std::string &bundleName) = 0; - virtual std::shared_ptr ConnectAssetLoader(uint32_t tokenId, const Database &dbMeta) = 0; - virtual std::shared_ptr ConnectCloudDB(uint32_t tokenId, const Database &dbMeta) = 0; + virtual CloudInfo GetServerInfo(int32_t userId); + virtual SchemaMeta GetAppSchema(int32_t userId, const std::string &bundleName); + virtual std::shared_ptr ConnectAssetLoader(uint32_t tokenId, const Database &dbMeta); + virtual std::shared_ptr ConnectCloudDB(uint32_t tokenId, const Database &dbMeta); private: static CloudServer *instance_; diff --git a/datamgr_service/services/distributeddataservice/framework/include/store/auto_cache.h b/datamgr_service/services/distributeddataservice/framework/include/store/auto_cache.h index 3476e23f..6a10aacd 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/store/auto_cache.h +++ b/datamgr_service/services/distributeddataservice/framework/include/store/auto_cache.h @@ -19,11 +19,13 @@ #include #include "concurrent_map.h" +#include "executor_pool.h" #include "metadata/store_meta_data.h" #include "store/general_store.h" #include "store/general_value.h" #include "store/general_watcher.h" -#include "executor_pool.h" +#include "visibility.h" + namespace OHOS::DistributedData { class AutoCache { public: @@ -35,13 +37,19 @@ public: using Executor = ExecutorPool; using TaskId = ExecutorPool::TaskId; using Creator = std::function; - static AutoCache &GetInstance(); - int32_t RegCreator(int32_t type, Creator creator); - void Bind(std::shared_ptr executor); - Store GetStore(const StoreMetaData &meta, const Watchers &watchers); - void CloseStore(uint32_t tokenId, const std::string &storeId); - void CloseExcept(const std::set &users); - void SetObserver(uint32_t tokenId, const std::string &storeId, const Watchers &watchers); + API_EXPORT static AutoCache &GetInstance(); + + API_EXPORT int32_t RegCreator(int32_t type, Creator creator); + + API_EXPORT void Bind(std::shared_ptr executor); + + API_EXPORT Store GetStore(const StoreMetaData &meta, const Watchers &watchers); + + API_EXPORT void CloseStore(uint32_t tokenId, const std::string &storeId); + + API_EXPORT void CloseExcept(const std::set &users); + + API_EXPORT void SetObserver(uint32_t tokenId, const std::string &storeId, const Watchers &watchers); private: AutoCache(); @@ -50,7 +58,7 @@ private: struct Delegate : public GeneralWatcher { Delegate(GeneralStore *delegate, const Watchers &watchers, int32_t user); ~Delegate(); - operator Store (); + operator Store(); bool operator<(const Time &time) const; bool Close(); int32_t GetUser() const; @@ -66,12 +74,10 @@ private: std::shared_mutex mutex_; }; static constexpr int64_t INTERVAL = 1; - static constexpr size_t TIME_TASK_NUM = 1; std::shared_ptr executor_; TaskId taskId_ = Executor::INVALID_TASK_ID; ConcurrentMap> stores_; std::vector creators_; }; } // namespace OHOS::DistributedData - #endif // OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_STORE_STORE_AUTO_CACHE_H diff --git a/datamgr_service/services/distributeddataservice/framework/include/store/general_store.h b/datamgr_service/services/distributeddataservice/framework/include/store/general_store.h index d2006b5b..353390d2 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/store/general_store.h +++ b/datamgr_service/services/distributeddataservice/framework/include/store/general_store.h @@ -28,18 +28,24 @@ public: using Devices = std::vector; virtual ~GeneralStore() = default; + virtual int32_t Close() = 0; + virtual int32_t Execute(const std::string &table, const std::string &sql) = 0; - virtual int32_t Insert(const std::string &table, VBucket &&values) = 0; + virtual int32_t BatchInsert(const std::string &table, VBuckets &&values) = 0; - virtual int32_t Update(const std::string &table, const std::string &sql, VBucket &&values) = 0; + virtual int32_t BatchUpdate(const std::string &table, const std::string &sql, VBuckets &&values) = 0; + virtual int32_t Delete(const std::string &table, const std::string &sql, Values &&args) = 0; + virtual std::shared_ptr Query(const std::string &table, const std::string &sql, Values &&args) = 0; + + virtual int32_t Sync(const Devices &devices, int32_t mode, const GenQuery &query, Async async, int32_t wait) = 0; + virtual int32_t Watch(int32_t origin, Watcher &watcher) = 0; + virtual int32_t Unwatch(int32_t origin, Watcher &watcher) = 0; - virtual int32_t Sync(const Devices &devices, int32_t mode, const GenQuery &query, Async async) = 0; - virtual int32_t Sync(const Devices &devices, int32_t mode, const GenQuery &query, Async async, bool wait) = 0; }; } // namespace OHOS::DistributedData #endif // OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_STORE_GENERAL_STORE_H diff --git a/datamgr_service/services/distributeddataservice/framework/include/store/general_watcher.h b/datamgr_service/services/distributeddataservice/framework/include/store/general_watcher.h index d4c2b32d..52130eab 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/store/general_watcher.h +++ b/datamgr_service/services/distributeddataservice/framework/include/store/general_watcher.h @@ -28,13 +28,15 @@ public: ORIGIN_ALL, ORIGIN_BUTT, }; + enum ChangeOp : int32_t { OP_INSERT, OP_UPDATE, OP_DELETE, OP_BUTT, }; - API_EXPORT virtual ~GeneralWatcher() = default; + + virtual ~GeneralWatcher() = default; virtual int32_t OnChange(Origin origin, const std::string &id) = 0; virtual int32_t OnChange(Origin origin, const std::string &id, const std::vector &values) = 0; }; diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_general_store.cpp b/datamgr_service/services/distributeddataservice/service/rdb/rdb_general_store.cpp index cbfa6624..18515925 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_general_store.cpp +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_general_store.cpp @@ -80,13 +80,6 @@ int32_t RdbGeneralStore::Execute(const std::string &table, const std::string &sq return GeneralError::E_ERROR; } -int32_t RdbGeneralStore::Insert(const std::string &table, VBucket &&values) -{ - int64_t outRowId; - auto ret = store_->Insert(outRowId, table, Convert(std::move(values))); - return (ret == NativeRdb::E_OK) ? GeneralError::E_OK : GeneralError::E_ERROR; -} - int32_t RdbGeneralStore::BatchInsert(const std::string &table, VBuckets &&values) { std::vector rdbVBucket; @@ -101,35 +94,32 @@ int32_t RdbGeneralStore::BatchInsert(const std::string &table, VBuckets &&values return GeneralError::E_ERROR; } -int32_t RdbGeneralStore::Update(const std::string &table, const std::string &sql, VBucket &&values) -{ - return 0; -} int32_t RdbGeneralStore::BatchUpdate(const std::string &table, const std::string &sql, VBuckets &&values) { return 0; } + int32_t RdbGeneralStore::Delete(const std::string &table, const std::string &sql, Values &&args) { return 0; } + std::shared_ptr RdbGeneralStore::Query(const std::string &table, const std::string &sql, Values &&args) { return std::shared_ptr(); } + int32_t RdbGeneralStore::Watch(int32_t origin, Watcher &watcher) { return 0; } + int32_t RdbGeneralStore::Unwatch(int32_t origin, Watcher &watcher) { return 0; } -int32_t RdbGeneralStore::Sync(const Devices &devices, int32_t mode, const GenQuery &query, Async async) -{ - return 0; -} -int32_t RdbGeneralStore::Sync(const Devices &devices, int32_t mode, const GenQuery &query, Async async, bool wait) + +int32_t RdbGeneralStore::Sync(const Devices &devices, int32_t mode, const GenQuery &query, Async async, int32_t wait) { return 0; } diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_general_store.h b/datamgr_service/services/distributeddataservice/service/rdb/rdb_general_store.h index 128774b7..b79bbb07 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_general_store.h +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_general_store.h @@ -37,16 +37,13 @@ public: RdbGeneralStore(const StoreMetaData &metaData); int32_t Close() override; int32_t Execute(const std::string &table, const std::string &sql) override; - int32_t Insert(const std::string &table, VBucket &&values) override; int32_t BatchInsert(const std::string &table, VBuckets &&values) override; - int32_t Update(const std::string &table, const std::string &sql, VBucket &&values) override; int32_t BatchUpdate(const std::string &table, const std::string &sql, VBuckets &&values) override; int32_t Delete(const std::string &table, const std::string &sql, Values &&args) override; std::shared_ptr Query(const std::string &table, const std::string &sql, Values &&args) override; int32_t Watch(int32_t origin, Watcher &watcher) override; int32_t Unwatch(int32_t origin, Watcher &watcher) override; - int32_t Sync(const Devices &devices, int32_t mode, const GenQuery &query, Async async) override; - int32_t Sync(const Devices &devices, int32_t mode, const GenQuery &query, Async async, bool wait) override; + int32_t Sync(const Devices &devices, int32_t mode, const GenQuery &query, Async async, int32_t wait) override; private: NativeRdb::ValuesBucket Convert(DistributedData::VBucket &&bucket); -- Gitee From d6c4d960dae14caf6bf991fc42215161ae27fae1 Mon Sep 17 00:00:00 2001 From: Sven Wang Date: Wed, 26 Apr 2023 14:20:45 +0800 Subject: [PATCH 41/44] update Signed-off-by: Sven Wang --- .../distributeddataservice/adapter/BUILD.gn | 2 +- .../distributeddataservice/framework/BUILD.gn | 1 + .../framework/cloud/cloud_db.cpp | 5 ++ .../framework/include/cloud/cloud_db.h | 1 + .../include/error/general_error.h} | 52 ++++++------------- .../framework/include/store/auto_cache.h | 7 ++- .../framework/include/store/general_store.h | 2 + .../framework/include/store/general_value.h | 13 +---- .../framework/serializable/serializable.cpp | 1 + .../framework/store/auto_cache.cpp | 9 +++- .../service/bootstrap/src/bootstrap.cpp | 6 +-- .../service/data_share/rdb_adaptor.cpp | 2 +- .../service/rdb/rdb_general_store.cpp | 18 ++++--- .../service/rdb/rdb_general_store.h | 1 + kv_store/frameworks/common/traits.h | 18 +++++-- 15 files changed, 65 insertions(+), 73 deletions(-) rename datamgr_service/services/distributeddataservice/{app/test/unittest/uninstaller_test.cpp => framework/include/error/general_error.h} (41%) diff --git a/datamgr_service/services/distributeddataservice/adapter/BUILD.gn b/datamgr_service/services/distributeddataservice/adapter/BUILD.gn index 34abe79d..c1e309f1 100644 --- a/datamgr_service/services/distributeddataservice/adapter/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/adapter/BUILD.gn @@ -24,7 +24,7 @@ config("distributeddata_adapter_private_config") { } config("distributeddata_adapter_public_config") { - visibility = [ "//foundation/distributeddatamgr/datamgr_service:*" ] + visibility = [ ":*" ] include_dirs = [ "include/log", diff --git a/datamgr_service/services/distributeddataservice/framework/BUILD.gn b/datamgr_service/services/distributeddataservice/framework/BUILD.gn index 7beccd12..ea3b510f 100644 --- a/datamgr_service/services/distributeddataservice/framework/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/framework/BUILD.gn @@ -56,6 +56,7 @@ ohos_shared_library("distributeddatasvcfwk") { "metadata/strategy_meta_data.cpp", "metadata/user_meta_data.cpp", "serializable/serializable.cpp", + "store/auto_cache.cpp", "utils/anonymous.cpp", "utils/block_integer.cpp", "utils/constant.cpp", diff --git a/datamgr_service/services/distributeddataservice/framework/cloud/cloud_db.cpp b/datamgr_service/services/distributeddataservice/framework/cloud/cloud_db.cpp index 058bdab9..ea4d041d 100644 --- a/datamgr_service/services/distributeddataservice/framework/cloud/cloud_db.cpp +++ b/datamgr_service/services/distributeddataservice/framework/cloud/cloud_db.cpp @@ -45,6 +45,11 @@ std::shared_ptr CloudDB::Query(const std::string &table, const std::stri return nullptr; } +std::shared_ptr CloudDB::Query(const std::string &table, const GenQuery &query) +{ + return nullptr; +} + int32_t CloudDB::Sync(const Devices &devices, int32_t mode, const GenQuery &query, Async async, int32_t wait) { return E_NOT_SUPPORT; diff --git a/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_db.h b/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_db.h index 7f8caa66..9b67c9a4 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_db.h +++ b/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_db.h @@ -26,6 +26,7 @@ public: int32_t BatchUpdate(const std::string &table, const std::string &sql, VBuckets &&values) override; int32_t Delete(const std::string &table, const std::string &sql, Values &&args) override; std::shared_ptr Query(const std::string &table, const std::string &sql, Values &&args) override; + std::shared_ptr Query(const std::string &table, const GenQuery &query) override; int32_t Sync(const Devices &devices, int32_t mode, const GenQuery &query, Async async, int32_t wait) override; int32_t Watch(int32_t origin, Watcher &watcher) override; int32_t Unwatch(int32_t origin, Watcher &watcher) override; diff --git a/datamgr_service/services/distributeddataservice/app/test/unittest/uninstaller_test.cpp b/datamgr_service/services/distributeddataservice/framework/include/error/general_error.h similarity index 41% rename from datamgr_service/services/distributeddataservice/app/test/unittest/uninstaller_test.cpp rename to datamgr_service/services/distributeddataservice/framework/include/error/general_error.h index dedd386d..8c60a916 100644 --- a/datamgr_service/services/distributeddataservice/app/test/unittest/uninstaller_test.cpp +++ b/datamgr_service/services/distributeddataservice/framework/include/error/general_error.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * 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 @@ -13,41 +13,19 @@ * limitations under the License. */ -#include -#include "uninstaller/uninstaller.h" - -using namespace testing::ext; -using namespace OHOS::DistributedKv; - -class UninstallerTest : public testing::Test { -public: - static void SetUpTestCase(void); - static void TearDownTestCase(void); - void SetUp(); - void TearDown(); +#ifndef OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_STORE_GENERAL_ERROR_H +#define OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_STORE_GENERAL_ERROR_H +namespace OHOS::DistributedData { +enum GeneralError : int32_t { + E_OK = 0, + E_ERROR, + E_BUSY, + E_INVALID_ARGS, + E_NOT_INIT, + E_NOT_SUPPORT, + E_ALREADY_CONSUMED, + E_ALREADY_CLOSED, + E_BUTT, }; - -void UninstallerTest::SetUpTestCase(void) -{} - -void UninstallerTest::TearDownTestCase(void) -{} - -void UninstallerTest::SetUp(void) -{} - -void UninstallerTest::TearDown(void) -{} - -/** - * @tc.name: Test001 - * @tc.desc: test get uninstaller instance. - * @tc.type: FUNC - * @tc.require: SR000DOGUN AR000DPSE9 - * @tc.author: hongbo - */ -HWTEST_F(UninstallerTest, Test001, TestSize.Level0) -{ - auto &unin = Uninstaller::GetInstance(); - unin.Init(nullptr); } +#endif // OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_STORE_GENERAL_ERROR_H diff --git a/datamgr_service/services/distributeddataservice/framework/include/store/auto_cache.h b/datamgr_service/services/distributeddataservice/framework/include/store/auto_cache.h index 6a10aacd..ffed302f 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/store/auto_cache.h +++ b/datamgr_service/services/distributeddataservice/framework/include/store/auto_cache.h @@ -19,13 +19,13 @@ #include #include "concurrent_map.h" +#include "error/general_error.h" #include "executor_pool.h" #include "metadata/store_meta_data.h" #include "store/general_store.h" #include "store/general_value.h" #include "store/general_watcher.h" #include "visibility.h" - namespace OHOS::DistributedData { class AutoCache { public: @@ -73,11 +73,14 @@ private: int32_t user_; std::shared_mutex mutex_; }; + static constexpr int64_t INTERVAL = 1; + static constexpr int32_t MAX_CREATOR_NUM = 30; + std::shared_ptr executor_; TaskId taskId_ = Executor::INVALID_TASK_ID; ConcurrentMap> stores_; - std::vector creators_; + Creator creators_[MAX_CREATOR_NUM]; }; } // namespace OHOS::DistributedData #endif // OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_STORE_STORE_AUTO_CACHE_H diff --git a/datamgr_service/services/distributeddataservice/framework/include/store/general_store.h b/datamgr_service/services/distributeddataservice/framework/include/store/general_store.h index 353390d2..3b88c4f4 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/store/general_store.h +++ b/datamgr_service/services/distributeddataservice/framework/include/store/general_store.h @@ -41,6 +41,8 @@ public: virtual std::shared_ptr Query(const std::string &table, const std::string &sql, Values &&args) = 0; + virtual std::shared_ptr Query(const std::string &table, const GenQuery &query) = 0; + virtual int32_t Sync(const Devices &devices, int32_t mode, const GenQuery &query, Async async, int32_t wait) = 0; virtual int32_t Watch(int32_t origin, Watcher &watcher) = 0; diff --git a/datamgr_service/services/distributeddataservice/framework/include/store/general_value.h b/datamgr_service/services/distributeddataservice/framework/include/store/general_value.h index 108ca00d..ad2e3141 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/store/general_value.h +++ b/datamgr_service/services/distributeddataservice/framework/include/store/general_value.h @@ -21,19 +21,8 @@ #include #include #include "traits.h" +#include "error/general_error.h" namespace OHOS::DistributedData { -enum GeneralError : int32_t { - E_OK = 0, - E_ERROR, - E_BUSY, - E_INVALID_ARGS, - E_NOT_INIT, - E_NOT_SUPPORT, - E_ALREADY_CONSUMED, - E_ALREADY_CLOSED, - E_BUTT, -}; - struct Asset { uint32_t version; std::string name; diff --git a/datamgr_service/services/distributeddataservice/framework/serializable/serializable.cpp b/datamgr_service/services/distributeddataservice/framework/serializable/serializable.cpp index c9b62933..509880a8 100644 --- a/datamgr_service/services/distributeddataservice/framework/serializable/serializable.cpp +++ b/datamgr_service/services/distributeddataservice/framework/serializable/serializable.cpp @@ -171,6 +171,7 @@ bool Serializable::SetValue(json &node, const uint64_t &value) node = value; return true; } + bool Serializable::SetValue(json &node, const bool &value) { node = value; diff --git a/datamgr_service/services/distributeddataservice/framework/store/auto_cache.cpp b/datamgr_service/services/distributeddataservice/framework/store/auto_cache.cpp index a488709a..212f6c1b 100644 --- a/datamgr_service/services/distributeddataservice/framework/store/auto_cache.cpp +++ b/datamgr_service/services/distributeddataservice/framework/store/auto_cache.cpp @@ -25,8 +25,8 @@ AutoCache &AutoCache::GetInstance() int32_t AutoCache::RegCreator(int32_t type, Creator creator) { - if (type >= creators_.size()) { - creators_.resize(type + 1); + if (type >= MAX_CREATOR_NUM) { + return E_ERROR; } creators_[type] = creator; return 0; @@ -43,6 +43,7 @@ void AutoCache::Bind(std::shared_ptr executor) } AutoCache::AutoCache() {} + AutoCache::~AutoCache() { GarbageCollect(true); @@ -54,6 +55,10 @@ AutoCache::~AutoCache() AutoCache::Store AutoCache::GetStore(const StoreMetaData &meta, const Watchers &watchers) { Store store; + if (meta.storeType >= MAX_CREATOR_NUM || !creators_[meta.storeType]) { + return store; + } + stores_.Compute(meta.tokenId, [this, &meta, &watchers, &store](auto &, std::map &stores) -> bool { auto it = stores.find(meta.storeId); diff --git a/datamgr_service/services/distributeddataservice/service/bootstrap/src/bootstrap.cpp b/datamgr_service/services/distributeddataservice/service/bootstrap/src/bootstrap.cpp index 96172649..741f18b9 100644 --- a/datamgr_service/services/distributeddataservice/service/bootstrap/src/bootstrap.cpp +++ b/datamgr_service/services/distributeddataservice/service/bootstrap/src/bootstrap.cpp @@ -58,12 +58,8 @@ void Bootstrap::LoadComponents() if (comp.lib.empty()) { continue; } - char path[PATH_MAX] = { 0 }; - if (realpath(comp.lib.c_str(), path) == NULL) { - continue; - } // no need to close the component, so we don't keep the handles - auto handle = dlopen(path, RTLD_LAZY); + auto handle = dlopen(comp.lib.c_str(), RTLD_LAZY); if (handle == nullptr) { ZLOGE("dlopen(%{public}s) failed(%{public}d)!", comp.lib.c_str(), errno); continue; diff --git a/datamgr_service/services/distributeddataservice/service/data_share/rdb_adaptor.cpp b/datamgr_service/services/distributeddataservice/service/data_share/rdb_adaptor.cpp index 31e452fc..d9916ea6 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/rdb_adaptor.cpp +++ b/datamgr_service/services/distributeddataservice/service/data_share/rdb_adaptor.cpp @@ -77,7 +77,7 @@ RdbDelegate::RdbDelegate(const StoreMetaData &meta, int &errCode) RdbDelegate::~RdbDelegate() { - ZLOGI("destroy"); + ZLOGD("destroy"); } int64_t RdbDelegate::Insert(const std::string &tableName, const DataShareValuesBucket &valuesBucket) diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_general_store.cpp b/datamgr_service/services/distributeddataservice/service/rdb/rdb_general_store.cpp index 18515925..ea4ae3ae 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_general_store.cpp +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_general_store.cpp @@ -14,6 +14,7 @@ */ #define LOG_TAG "RdbGeneralStore" #include "rdb_general_store.h" + #include "crypto_manager.h" #include "log_print.h" #include "metadata/meta_data_manager.h" @@ -109,6 +110,11 @@ std::shared_ptr RdbGeneralStore::Query(const std::string &table, const s return std::shared_ptr(); } +std::shared_ptr RdbGeneralStore::Query(const std::string &table, const GenQuery &query) +{ + return std::shared_ptr(); +} + int32_t RdbGeneralStore::Watch(int32_t origin, Watcher &watcher) { return 0; @@ -191,27 +197,23 @@ DistributedData::Value RdbGeneralStore::Convert(ValueObject &&rdbValue) NativeRdb::AssetValue RdbGeneralStore::ConvertAsset(Asset &&value) { - return NativeRdb::AssetValue{ - .version = std::move(value.version), + return NativeRdb::AssetValue{ .version = std::move(value.version), .name = std::move(value.name), .uri = std::move(value.uri), .createTime = std::move(value.createTime), .modifyTime = std::move(value.modifyTime), .size = std::move(value.size), - .hash = std::move(value.hash) - }; + .hash = std::move(value.hash) }; } DistributedData::Asset RdbGeneralStore::ConvertAsset(AssetValue &&value) { - return DistributedData::Asset { - .version = std::move(value.version), + return DistributedData::Asset{ .version = std::move(value.version), .name = std::move(value.name), .uri = std::move(value.uri), .createTime = std::move(value.createTime), .modifyTime = std::move(value.modifyTime), .size = std::move(value.size), - .hash = std::move(value.hash) - }; + .hash = std::move(value.hash) }; } } // namespace OHOS::DistributedRdb diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_general_store.h b/datamgr_service/services/distributeddataservice/service/rdb/rdb_general_store.h index b79bbb07..dc7aa0d6 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_general_store.h +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_general_store.h @@ -41,6 +41,7 @@ public: int32_t BatchUpdate(const std::string &table, const std::string &sql, VBuckets &&values) override; int32_t Delete(const std::string &table, const std::string &sql, Values &&args) override; std::shared_ptr Query(const std::string &table, const std::string &sql, Values &&args) override; + std::shared_ptr Query(const std::string &table, const GenQuery &query) override; int32_t Watch(int32_t origin, Watcher &watcher) override; int32_t Unwatch(int32_t origin, Watcher &watcher) override; int32_t Sync(const Devices &devices, int32_t mode, const GenQuery &query, Async async, int32_t wait) override; diff --git a/kv_store/frameworks/common/traits.h b/kv_store/frameworks/common/traits.h index 3a4c0023..26c74730 100644 --- a/kv_store/frameworks/common/traits.h +++ b/kv_store/frameworks/common/traits.h @@ -20,18 +20,27 @@ #include namespace OHOS { namespace Traits { +template +struct index_of : std::integral_constant {}; + +template +inline constexpr size_t index_of_v = index_of::value; + +template +struct index_of + : std::integral_constant ? 0 : index_of_v + 1> {}; + // If there is one in the ...Types, that is equal to T. same_index_of_v is the index. // If there is no one in the ...Types, that is equal to T. same_index_of_v is sizeof ...(Types) template -inline constexpr size_t same_index_of_v = std::__detail::__variant::__index_of_v; +inline constexpr size_t same_index_of_v = index_of::value; // There is one in the ...Types, that is equal to T. If not, the same_in_v will be false. template inline constexpr bool same_in_v = (same_index_of_v < sizeof...(Types)); template -struct convertible_index_of : std::integral_constant { -}; +struct convertible_index_of : std::integral_constant {}; // If there is one in the ...Types that can convert to T implicitly, convertible_index_v is the index. // If there is no one in the ...Types that can convert to T implicitly, convertible_index_v is sizeof ...(Types) @@ -40,8 +49,7 @@ inline constexpr size_t convertible_index_of_v = convertible_index_of struct convertible_index_of - : std::integral_constant ? 0 : convertible_index_of_v + 1> { -}; + : std::integral_constant ? 0 : convertible_index_of_v + 1> {}; // There is one in the ...Types, that can convert to T implicitly. If not, the convertible_in_v will be false. template -- Gitee From 11643de1c555b70a1a3a8222ab07f35b13106c87 Mon Sep 17 00:00:00 2001 From: Sven Wang Date: Wed, 26 Apr 2023 20:27:27 +0800 Subject: [PATCH 42/44] update Signed-off-by: Sven Wang --- .../framework/cloud/cloud_info.cpp | 23 ------------------- .../framework/include/cloud/cloud_info.h | 3 --- .../framework/include/store/general_value.h | 12 +++++----- .../service/cloud/cloud_service_impl.cpp | 13 +++++++---- .../service/rdb/rdb_general_store.cpp | 16 ++++++++----- 5 files changed, 24 insertions(+), 43 deletions(-) diff --git a/datamgr_service/services/distributeddataservice/framework/cloud/cloud_info.cpp b/datamgr_service/services/distributeddataservice/framework/cloud/cloud_info.cpp index be368f11..f3f141eb 100644 --- a/datamgr_service/services/distributeddataservice/framework/cloud/cloud_info.cpp +++ b/datamgr_service/services/distributeddataservice/framework/cloud/cloud_info.cpp @@ -92,29 +92,6 @@ bool CloudInfo::IsExist(const std::string &bundleName) const return false; } -void CloudInfo::UpdateApp(const std::vector &appInfos) -{ - auto tmpInfo = appInfos; - for (auto &info : tmpInfo) { - auto app = GetApp(info.bundleName); - if (app.bundleName.empty()) { - continue; - } - info.cloudSwitch = app.cloudSwitch; - } - apps = tmpInfo; -} - -CloudInfo::AppInfo &CloudInfo::GetApp(const std::string &bundleName) -{ - for (auto &app : apps) { - if (app.bundleName == bundleName) { - return app; - } - } - return appNil_; -} - std::string CloudInfo::GetPrefix(const std::initializer_list &fields) { return GetKey(INFO_PREFIX, fields).append(Constant::KEY_SEPARATOR); diff --git a/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_info.h b/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_info.h index c7d2cd17..5576bca8 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_info.h +++ b/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_info.h @@ -40,8 +40,6 @@ public: std::string GetSchemaKey(std::string bundleName) const; bool IsValid() const; bool IsExist(const std::string &bundleName) const; - void UpdateApp(const std::vector &appInfos); - AppInfo &GetApp(const std::string &bundleName); static std::string GetPrefix(const std::initializer_list &field); bool Marshal(json &node) const override; @@ -52,7 +50,6 @@ private: static constexpr const char *SCHEMA_PREFIX = "CLOUD_SCHEMA"; static std::string GetKey(const std::string &prefix, const std::initializer_list &fields); - AppInfo appNil_ {}; }; } #endif // OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_CLOUD_CLOUD_INFO_H diff --git a/datamgr_service/services/distributeddataservice/framework/include/store/general_value.h b/datamgr_service/services/distributeddataservice/framework/include/store/general_value.h index ad2e3141..eca104b1 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/store/general_value.h +++ b/datamgr_service/services/distributeddataservice/framework/include/store/general_value.h @@ -51,26 +51,26 @@ inline constexpr size_t TYPE_INDEX = Traits::variant_index_of_v; inline constexpr size_t TYPE_MAX = Traits::variant_size_of_v; template -bool GetItem(const T &input, O &output) +bool GetItem(T &&input, O &output) { return false; } template -bool GetItem(const T &input, O &output) +bool GetItem(T &&input, O &output) { auto val = Traits::get_if(&input); if (val != nullptr) { - output = *val; + output = std::move(*val); return true; } - return GetItem(input, output); + return GetItem(std::move(input), output); } template -bool Convert(const T &input, std::variant &output) +bool Convert(T &&input, std::variant &output) { - return GetItem(input, output); + return GetItem(std::move(input), output); } } // namespace OHOS::DistributedData #endif // OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_STORE_GENERAL_VALUE_H diff --git a/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.cpp b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.cpp index 334f7277..9f51ad40 100644 --- a/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.cpp +++ b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.cpp @@ -101,7 +101,7 @@ int32_t CloudServiceImpl::EnableCloud(const std::string &id, const std::map bool { + return appInfo.bundleName == bundleName; + }); + if (it == cloudInfo.apps.end()) { ZLOGE("bundleName:%{public}s", bundleName.c_str()); return INVALID_ARGUMENT; } - app.cloudSwitch = appSwitch; + (*it).cloudSwitch = appSwitch; if (!MetaDataManager::GetInstance().SaveMeta(cloudInfo.GetKey(), cloudInfo, true)) { return ERROR; } @@ -222,7 +225,7 @@ void CloudServiceImpl::UpdateCloudInfo(CloudInfo &cloudInfo) } oldInfo.totalSpace = cloudInfo.totalSpace; oldInfo.remainSpace = cloudInfo.remainSpace; - oldInfo.UpdateApp(cloudInfo.apps); + oldInfo.apps = std::move(cloudInfo.apps); cloudInfo = oldInfo; MetaDataManager::GetInstance().SaveMeta(oldInfo.GetKey(), oldInfo, true); } diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_general_store.cpp b/datamgr_service/services/distributeddataservice/service/rdb/rdb_general_store.cpp index ea4ae3ae..823472a7 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_general_store.cpp +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_general_store.cpp @@ -142,9 +142,6 @@ NativeRdb::ValuesBucket RdbGeneralStore::Convert(VBucket &&bucket) NativeRdb::ValueObject RdbGeneralStore::Convert(Value &&value) { ValueObject rdbValue; - if (DistributedData::Convert(rdbValue.value, value)) { - return rdbValue; - } if (value.index() == TYPE_INDEX) { Asset *asset = Traits::get_if(&value); if (asset == nullptr) { @@ -164,15 +161,17 @@ NativeRdb::ValueObject RdbGeneralStore::Convert(Value &&value) } return std::move(assetsValue); } + + if (DistributedData::Convert(std::move(value), rdbValue.value)) { + return rdbValue; + } + return NativeRdb::ValueObject(); } DistributedData::Value RdbGeneralStore::Convert(ValueObject &&rdbValue) { DistributedData::Value value; - if (DistributedData::Convert(rdbValue.value, value)) { - return value; - } if (rdbValue.value.index() == Traits::variant_index_of_v) { auto *rdbAsset = Traits::get_if(&rdbValue.value); if (rdbAsset == nullptr) { @@ -192,6 +191,11 @@ DistributedData::Value RdbGeneralStore::Convert(ValueObject &&rdbValue) } return std::move(assets); } + + if (DistributedData::Convert(std::move(rdbValue.value), value)) { + return value; + } + return value; } -- Gitee From 77a722c5383d1e5a6a01b1ebb73163f98610d9a6 Mon Sep 17 00:00:00 2001 From: Sven Wang Date: Wed, 26 Apr 2023 20:37:02 +0800 Subject: [PATCH 43/44] update Signed-off-by: Sven Wang --- .../service/rdb/rdb_general_store.cpp | 43 +++++-------------- 1 file changed, 11 insertions(+), 32 deletions(-) diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_general_store.cpp b/datamgr_service/services/distributeddataservice/service/rdb/rdb_general_store.cpp index 823472a7..ce64900b 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_general_store.cpp +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_general_store.cpp @@ -142,19 +142,12 @@ NativeRdb::ValuesBucket RdbGeneralStore::Convert(VBucket &&bucket) NativeRdb::ValueObject RdbGeneralStore::Convert(Value &&value) { ValueObject rdbValue; - if (value.index() == TYPE_INDEX) { - Asset *asset = Traits::get_if(&value); - if (asset == nullptr) { - return NativeRdb::ValueObject(); - } + auto *asset = Traits::get_if(&value); + if (asset != nullptr) { return ConvertAsset(std::move(*asset)); } - - if (value.index() == TYPE_INDEX) { - auto *assets = Traits::get_if(&value); - if (assets == nullptr) { - return NativeRdb::ValueObject(); - } + auto *assets = Traits::get_if(&value); + if (assets != nullptr) { std::vector assetsValue; for (auto &asset : *assets) { assetsValue.push_back(ConvertAsset(std::move(asset))); @@ -162,40 +155,26 @@ NativeRdb::ValueObject RdbGeneralStore::Convert(Value &&value) return std::move(assetsValue); } - if (DistributedData::Convert(std::move(value), rdbValue.value)) { - return rdbValue; - } - - return NativeRdb::ValueObject(); + DistributedData::Convert(std::move(value), rdbValue.value); + return rdbValue; } DistributedData::Value RdbGeneralStore::Convert(ValueObject &&rdbValue) { DistributedData::Value value; - if (rdbValue.value.index() == Traits::variant_index_of_v) { - auto *rdbAsset = Traits::get_if(&rdbValue.value); - if (rdbAsset == nullptr) { - return {}; - } + auto *rdbAsset = Traits::get_if(&rdbValue.value); + if (rdbAsset != nullptr) { return ConvertAsset(std::move(*rdbAsset)); } - - if (rdbValue.value.index() == Traits::variant_index_of_v) { - auto *rdbAssets = Traits::get_if(&value); - if (rdbAssets == nullptr) { - return value; - } + auto *rdbAssets = Traits::get_if(&rdbValue.value); + if (rdbAssets != nullptr) { Assets assets; for (auto &rdbAsset : *rdbAssets) { assets.push_back(ConvertAsset(std::move(rdbAsset))); } return std::move(assets); } - - if (DistributedData::Convert(std::move(rdbValue.value), value)) { - return value; - } - + DistributedData::Convert(std::move(rdbValue.value), value); return value; } -- Gitee From 8e39dfdecd2cfeda0272278e40013d8a415ef552 Mon Sep 17 00:00:00 2001 From: ylq121 Date: Wed, 26 Apr 2023 22:03:04 +0800 Subject: [PATCH 44/44] cloudSync-napi Signed-off-by: ylq121 --- .../service/cloud/cloud_service_stub.cpp | 32 +++ .../frameworks/js/napi/cloud_data/BUILD.gn | 56 +++++ .../js/napi/cloud_data/include/js_config.h | 37 +++ .../cloud_data/include/js_const_properties.h | 25 ++ .../napi/cloud_data/include/js_error_utils.h | 69 ++++++ .../js/napi/cloud_data/include/js_util.h | 95 ++++++++ .../js/napi/cloud_data/include/napi_queue.h | 142 +++++++++++ .../js/napi/cloud_data/src/entry_point.cpp | 50 ++++ .../js/napi/cloud_data/src/js_config.cpp | 221 ++++++++++++++++++ .../cloud_data/src/js_const_properties.cpp | 53 +++++ .../js/napi/cloud_data/src/js_error_utils.cpp | 91 ++++++++ .../js/napi/cloud_data/src/js_util.cpp | 166 +++++++++++++ .../js/napi/cloud_data/src/napi_queue.cpp | 163 +++++++++++++ 13 files changed, 1200 insertions(+) create mode 100644 relational_store/frameworks/js/napi/cloud_data/include/js_config.h create mode 100644 relational_store/frameworks/js/napi/cloud_data/include/js_const_properties.h create mode 100644 relational_store/frameworks/js/napi/cloud_data/include/js_error_utils.h create mode 100644 relational_store/frameworks/js/napi/cloud_data/include/js_util.h create mode 100644 relational_store/frameworks/js/napi/cloud_data/include/napi_queue.h create mode 100644 relational_store/frameworks/js/napi/cloud_data/src/entry_point.cpp create mode 100644 relational_store/frameworks/js/napi/cloud_data/src/js_config.cpp create mode 100644 relational_store/frameworks/js/napi/cloud_data/src/js_const_properties.cpp create mode 100644 relational_store/frameworks/js/napi/cloud_data/src/js_error_utils.cpp create mode 100644 relational_store/frameworks/js/napi/cloud_data/src/js_util.cpp create mode 100644 relational_store/frameworks/js/napi/cloud_data/src/napi_queue.cpp diff --git a/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_stub.cpp b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_stub.cpp index 2ccf869e..bdf8b5fb 100644 --- a/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_stub.cpp +++ b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_stub.cpp @@ -15,6 +15,8 @@ #define LOG_TAG "CloudServiceStub" #include "cloud_service_stub.h" +#include + #include "ipc_skeleton.h" #include "itypes_util.h" #include "log_print.h" @@ -53,6 +55,12 @@ int CloudServiceStub::OnRemoteRequest(uint32_t code, OHOS::MessageParcel &data, int32_t CloudServiceStub::OnEnableCloud(const std::string &id, MessageParcel &data, MessageParcel &reply) { + auto tokenId = IPCSkeleton::GetCallingTokenID(); + if (OHOS::Security::AccessToken::AccessTokenKit::GetTokenTypeFlag(tokenId) == + OHOS::Security::AccessToken::TOKEN_HAP) { + ZLOGE("permission denied!"); + return -1; + } std::map switches; if (!ITypesUtil::Unmarshal(data, switches)) { ZLOGE("Unmarshal id:%{public}s", Anonymous::Change(id).c_str()); @@ -64,12 +72,24 @@ int32_t CloudServiceStub::OnEnableCloud(const std::string &id, MessageParcel &da int32_t CloudServiceStub::OnDisableCloud(const std::string &id, MessageParcel &data, MessageParcel &reply) { + auto tokenId = IPCSkeleton::GetCallingTokenID(); + if (OHOS::Security::AccessToken::AccessTokenKit::GetTokenTypeFlag(tokenId) == + OHOS::Security::AccessToken::TOKEN_HAP) { + ZLOGE("permission denied!"); + return -1; + } auto result = DisableCloud(id); return ITypesUtil::Marshal(reply, result) ? ERR_NONE : IPC_STUB_WRITE_PARCEL_ERR; } int32_t CloudServiceStub::OnChangeAppSwitch(const std::string &id, MessageParcel &data, MessageParcel &reply) { + auto tokenId = IPCSkeleton::GetCallingTokenID(); + if (OHOS::Security::AccessToken::AccessTokenKit::GetTokenTypeFlag(tokenId) == + OHOS::Security::AccessToken::TOKEN_HAP) { + ZLOGE("permission denied!"); + return -1; + } std::string bundleName; int32_t appSwitch = SWITCH_OFF; if (!ITypesUtil::Unmarshal(data, bundleName, appSwitch)) { @@ -82,6 +102,12 @@ int32_t CloudServiceStub::OnChangeAppSwitch(const std::string &id, MessageParcel int32_t CloudServiceStub::OnClean(const std::string &id, MessageParcel &data, MessageParcel &reply) { + auto tokenId = IPCSkeleton::GetCallingTokenID(); + if (OHOS::Security::AccessToken::AccessTokenKit::GetTokenTypeFlag(tokenId) == + OHOS::Security::AccessToken::TOKEN_HAP) { + ZLOGE("permission denied!"); + return -1; + } std::map actions; if (!ITypesUtil::Unmarshal(data, actions)) { ZLOGE("Unmarshal id:%{public}s", Anonymous::Change(id).c_str()); @@ -93,6 +119,12 @@ int32_t CloudServiceStub::OnClean(const std::string &id, MessageParcel &data, Me int32_t CloudServiceStub::OnNotifyDataChange(const std::string &id, MessageParcel &data, MessageParcel &reply) { + auto tokenId = IPCSkeleton::GetCallingTokenID(); + if (OHOS::Security::AccessToken::AccessTokenKit::GetTokenTypeFlag(tokenId) == + OHOS::Security::AccessToken::TOKEN_HAP) { + ZLOGE("permission denied!"); + return -1; + } std::string bundleName; if (!ITypesUtil::Unmarshal(data, bundleName)) { ZLOGE("Unmarshal id:%{public}s", Anonymous::Change(id).c_str()); diff --git a/relational_store/frameworks/js/napi/cloud_data/BUILD.gn b/relational_store/frameworks/js/napi/cloud_data/BUILD.gn index e69de29b..fdd30566 100644 --- a/relational_store/frameworks/js/napi/cloud_data/BUILD.gn +++ b/relational_store/frameworks/js/napi/cloud_data/BUILD.gn @@ -0,0 +1,56 @@ +# 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. +import("//build/ohos.gni") +import("//build/ohos/ace/ace.gni") +import("//foundation/distributeddatamgr/relational_store/relational_store.gni") + +ohos_copy("relational_store_declaration") { + sources = [ "./api" ] + outputs = [ target_out_dir + "/$target_name/" ] + module_source_dir = target_out_dir + "/$target_name" + module_install_name = "" +} + +ohos_shared_library("clouddata") { + sources = [ + "src/entry_point.cpp", + "src/js_config.cpp", + "src/js_const_properties.cpp", + "src/js_error_utils.cpp", + "src/js_util.cpp", + "src/napi_queue.cpp", + ] + include_dirs = [ + "include", + "${relational_store_js_common_path}/include", + "${relational_store_napi_path}/cloud_data/include", + "${relational_store_innerapi_path}/cloud_data/include", + "//foundation/distributeddatamgr/kv_store/frameworks/common", + ] + defines = [ "SQLITE_DISTRIBUTE_RELATIONAL" ] + + external_deps = [ + "ability_runtime:abilitykit_native", + "ability_runtime:napi_base_context", + "c_utils:utils", + "hitrace_native:hitrace_meter", + "hiviewdfx_hilog_native:libhilog", + "napi:ace_napi", + "relational_store:native_appdatafwk", + "relational_store:native_rdb", + ] + + subsystem_name = "distributeddatamgr" + part_name = "relational_store" + relative_install_dir = "module/data" +} diff --git a/relational_store/frameworks/js/napi/cloud_data/include/js_config.h b/relational_store/frameworks/js/napi/cloud_data/include/js_config.h new file mode 100644 index 00000000..80b212fc --- /dev/null +++ b/relational_store/frameworks/js/napi/cloud_data/include/js_config.h @@ -0,0 +1,37 @@ +/* +* 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 LDBPROJ_JS_CONFIG_H +#define LDBPROJ_JS_CONFIG_H +#include "js_const_properties.h" +#include "js_util.h" +#include "log_print.h" + +namespace OHOS::CloudData { +class JsConfig { +public: + JsConfig(); + ~JsConfig(); + + static napi_value EnableCloud(napi_env env, napi_callback_info info); + static napi_value DisableCloud(napi_env env, napi_callback_info info); + static napi_value ChangeAppCloudSwitch(napi_env env, napi_callback_info info); + static napi_value Clean(napi_env env, napi_callback_info info); + static napi_value NotifyDataChange(napi_env env, napi_callback_info info); +}; + +} // namespace OHOS::CloudData + +#endif //LDBPROJ_JS_CONFIG_H diff --git a/relational_store/frameworks/js/napi/cloud_data/include/js_const_properties.h b/relational_store/frameworks/js/napi/cloud_data/include/js_const_properties.h new file mode 100644 index 00000000..6245a158 --- /dev/null +++ b/relational_store/frameworks/js/napi/cloud_data/include/js_const_properties.h @@ -0,0 +1,25 @@ +/* +* 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 LDBPROJ_JS_CONST_PROPERTIES_H +#define LDBPROJ_JS_CONST_PROPERTIES_H +#include "napi/native_api.h" +#include "napi/native_common.h" +#include "napi/native_node_api.h" + +namespace OHOS::CloudData { +napi_status InitConstProperties(napi_env env, napi_value exports); +} // namespace OHOS::CloudData +#endif //LDBPROJ_JS_CONST_PROPERTIES_H diff --git a/relational_store/frameworks/js/napi/cloud_data/include/js_error_utils.h b/relational_store/frameworks/js/napi/cloud_data/include/js_error_utils.h new file mode 100644 index 00000000..fbbbc6b7 --- /dev/null +++ b/relational_store/frameworks/js/napi/cloud_data/include/js_error_utils.h @@ -0,0 +1,69 @@ +/* +* 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 LDBPROJ_JS_ERROR_UTILS_H +#define LDBPROJ_JS_ERROR_UTILS_H +#include +#include + +#include "cloud_service.h" +#include "js_native_api.h" +#include "log_print.h" +#include "napi/native_common.h" + +namespace OHOS { +namespace CloudData { +using Status = OHOS::CloudData::CloudService::Status; + +struct JsErrorCode { + int32_t status; + int32_t jsCode; + const char *message; +}; + +const std::optional GetJsErrorCode(int32_t errorCode); +Status GenerateNapiError(Status status, int32_t &errCode, std::string &errMessage); +void ThrowNapiError(napi_env env, int32_t errCode, std::string errMessage, bool isParamsCheck = true); +napi_value GenerateErrorMsg(napi_env env, JsErrorCode jsInfo); + +#define ASSERT_ERR(env, assertion, errorCode, message) \ + do { \ + if (!(assertion)) { \ + ThrowNapiError(env, errorCode, message); \ + return nullptr; \ + } \ + } while (0) + +#define ASSERT_BUSINESS_ERR(ctxt, assertion, errorCode, message) \ + do { \ + if (!(assertion)) { \ + (ctxt)->isThrowError = true; \ + ThrowNapiError((ctxt)->env, errorCode, message); \ + return; \ + } \ + } while (0) + +#define ASSERT_PERMISSION_ERR(ctxt, assertion, errorCode, message) \ + do { \ + if (!(assertion)) { \ + (ctxt)->isThrowError = true; \ + ThrowNapiError((ctxt)->env, errorCode, message, false); \ + return; \ + } \ + } while (0) + +} // namespace CloudData +} // namespace OHOS +#endif //LDBPROJ_JS_ERROR_UTILS_H diff --git a/relational_store/frameworks/js/napi/cloud_data/include/js_util.h b/relational_store/frameworks/js/napi/cloud_data/include/js_util.h new file mode 100644 index 00000000..cc26fb01 --- /dev/null +++ b/relational_store/frameworks/js/napi/cloud_data/include/js_util.h @@ -0,0 +1,95 @@ +/* +* 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 LDBPROJ_JS_UTIL_H +#define LDBPROJ_JS_UTIL_H +#include +#include + +#include "js_error_utils.h" +#include "napi/native_api.h" +#include "napi/native_common.h" +#include "napi/native_node_api.h" + +namespace OHOS::CloudData { +class JSUtil final { +public: + enum { + /* exported js Action is (CloudData::Action-1) */ + CLEAR_CLOUD_INFO = 0, + CLEAR_CLOUD_DATA_AND_INFO = 1, + }; + + struct StatusMsg { + napi_status status = napi_ok; + StatusMsg(napi_status status) : status(status) {} + operator napi_status() + { + return status; + } + }; + + using Status = OHOS::CloudData::CloudService::Status; + + static StatusMsg GetValue(napi_env env, napi_value in, napi_value &out); + static StatusMsg SetValue(napi_env env, napi_value in, napi_value &out); + /* napi_value <-> bool */ + static StatusMsg GetValue(napi_env env, napi_value in, bool &out); + static StatusMsg SetValue(napi_env env, const bool &in, napi_value &out); + /* napi_value <-> std::string */ + static StatusMsg GetValue(napi_env env, napi_value in, std::string &out); + static StatusMsg SetValue(napi_env env, const std::string &in, napi_value &out); + /* napi_value <-> int32_t */ + static napi_status GetValue(napi_env env, napi_value in, int32_t &out); + static napi_status SetValue(napi_env env, const int32_t &in, napi_value &out); + /* napi_value <-> std::map */ + static StatusMsg GetValue(napi_env env, napi_value in, std::map &out); + static StatusMsg SetValue(napi_env env, const std::map &in, napi_value &out); + /* napi_value <-> std::map */ + static StatusMsg GetValue(napi_env env, napi_value in, std::map &out); + + /* napi_get_named_property wrapper */ + template + static inline napi_status GetNamedProperty(napi_env env, napi_value in, const std::string &prop, T &value) + { + bool hasProp = false; + napi_status status = napi_has_named_property(env, in, prop.c_str(), &hasProp); + if (!hasProp) { + return napi_generic_failure; + } + if ((status == napi_ok) && hasProp) { + napi_value inner = nullptr; + status = napi_get_named_property(env, in, prop.c_str(), &inner); + if ((status == napi_ok) && (inner != nullptr)) { + return GetValue(env, inner, value); + } + } + return napi_invalid_arg; + }; + + static bool ValidSubscribeType(int32_t type) + { + return (CLEAR_CLOUD_INFO <= type) && (type <= CLEAR_CLOUD_DATA_AND_INFO); + } + +private: + enum { + /* std::map to js::tuple */ + TUPLE_KEY = 0, + TUPLE_VALUE, + TUPLE_SIZE + }; +}; +} // namespace OHOS::CloudData +#endif //LDBPROJ_JS_UTIL_H diff --git a/relational_store/frameworks/js/napi/cloud_data/include/napi_queue.h b/relational_store/frameworks/js/napi/cloud_data/include/napi_queue.h new file mode 100644 index 00000000..3e92eed5 --- /dev/null +++ b/relational_store/frameworks/js/napi/cloud_data/include/napi_queue.h @@ -0,0 +1,142 @@ +/* + * 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 LDBPROJ_NAPI_QUEUE_H +#define LDBPROJ_NAPI_QUEUE_H +#include +#include +#include + +#include "log_print.h" +#include "napi/native_api.h" +#include "napi/native_common.h" +#include "napi/native_node_api.h" + +namespace OHOS::CloudData { +constexpr size_t ARGC_MAX = 6; +using NapiCbInfoParser = std::function; +using NapiAsyncExecute = std::function; +using NapiAsyncComplete = std::function; + +struct ContextBase { + virtual ~ContextBase(); + void GetCbInfo(napi_env env, napi_callback_info info, NapiCbInfoParser parse = NapiCbInfoParser(), + bool sync = false); + + inline void GetCbInfoSync(napi_env env, napi_callback_info info, NapiCbInfoParser parse = NapiCbInfoParser()) + { + /* sync = true, means no callback, not AsyncWork. */ + GetCbInfo(env, info, parse, true); + } + + napi_env env = nullptr; + napi_value output = nullptr; + napi_status status = napi_invalid_arg; + std::string error; + int32_t jsCode = 0; + bool isThrowError = false; + + napi_value self = nullptr; + void *native = nullptr; + +private: + napi_ref callbackRef = nullptr; + napi_ref selfRef = nullptr; + friend class NapiQueue; +}; + +/* check condition related to argc/argv, return and logging. */ +#define ASSERT_ARGS(ctxt, condition, message) \ + do { \ + if (!(condition)) { \ + (ctxt)->status = napi_invalid_arg; \ + (ctxt)->error = std::string(message); \ + ZLOGE("test (" #condition ") failed: " message); \ + return; \ + } \ + } while (0) + +#define ASSERT_STATUS(ctxt, message) \ + do { \ + if ((ctxt)->status != napi_ok) { \ + (ctxt)->error = std::string(message); \ + ZLOGE("test (ctxt->status == napi_ok) failed: " message); \ + return; \ + } \ + } while (0) + +/* check condition, return and logging if condition not true. */ +#define ASSERT(condition, message, retVal) \ + do { \ + if (!(condition)) { \ + ZLOGE("test (" #condition ") failed: " message); \ + return retVal; \ + } \ + } while (0) + +#define ASSERT_VOID(condition, message) \ + do { \ + if (!(condition)) { \ + ZLOGE("test (" #condition ") failed: " message); \ + return; \ + } \ + } while (0) + +#define ASSERT_NULL(condition, message) ASSERT(condition, message, nullptr) + +#define ASSERT_CALL(env, theCall, object) \ + do { \ + if ((theCall) != napi_ok) { \ + delete (object); \ + GET_AND_THROW_LAST_ERROR((env)); \ + return nullptr; \ + } \ + } while (0) + +class NapiQueue { +public: + static napi_value AsyncWork(napi_env env, std::shared_ptr ctxt, const std::string &name, + NapiAsyncExecute execute = NapiAsyncExecute(), NapiAsyncComplete complete = NapiAsyncComplete()); + +private: + enum { + /* AsyncCallback / Promise output result index */ + RESULT_ERROR = 0, + RESULT_DATA = 1, + RESULT_ALL = 2 + }; + + struct AsyncContext { + napi_env env = nullptr; + std::shared_ptr ctx; + NapiAsyncExecute execute = nullptr; + NapiAsyncComplete complete = nullptr; + napi_deferred deferred = nullptr; + napi_async_work work = nullptr; + ~AsyncContext() + { + execute = nullptr; + complete = nullptr; + ctx = nullptr; + if (env != nullptr) { + if (work != nullptr) { + napi_delete_async_work(env, work); + } + } + } + }; + static void GenerateOutput(AsyncContext &ctx, napi_value output); +}; +} // namespace OHOS::CloudData +#endif //LDBPROJ_NAPI_QUEUE_H diff --git a/relational_store/frameworks/js/napi/cloud_data/src/entry_point.cpp b/relational_store/frameworks/js/napi/cloud_data/src/entry_point.cpp new file mode 100644 index 00000000..12eb000a --- /dev/null +++ b/relational_store/frameworks/js/napi/cloud_data/src/entry_point.cpp @@ -0,0 +1,50 @@ +/* +* Copyright (c) 2023 Huawei Device Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +#define LOG_TAG "EntryPoint" +#include "js_config.h" +#include "js_const_properties.h" +#include "log_print.h" + +using namespace OHOS::CloudData; + +static napi_value Init(napi_env env, napi_value exports) +{ + const napi_property_descriptor desc[] = { + DECLARE_NAPI_FUNCTION("enableCloud", JsConfig::EnableCloud), + DECLARE_NAPI_FUNCTION("disableCloud", JsConfig::DisableCloud), + DECLARE_NAPI_FUNCTION("changeAppCloudSwitch", JsConfig::ChangeAppCloudSwitch), + DECLARE_NAPI_FUNCTION("clean", JsConfig::Clean), + DECLARE_NAPI_FUNCTION("notifyDataChange", JsConfig::NotifyDataChange), + + }; + napi_status status = napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc); + ZLOGI("init cloudData config %{public}d", status); + status = InitConstProperties(env, exports); + ZLOGI("init Enumerate Constants %{public}d", status); + return exports; +} + +static __attribute__((constructor)) void RegisterModule() +{ + static napi_module module = { .nm_version = 1, + .nm_flags = 0, + .nm_filename = nullptr, + .nm_register_func = Init, + .nm_modname = "data.cloudData", + .nm_priv = ((void *)0), + .reserved = { 0 } }; + napi_module_register(&module); + ZLOGI("module register data.cloudData"); +} diff --git a/relational_store/frameworks/js/napi/cloud_data/src/js_config.cpp b/relational_store/frameworks/js/napi/cloud_data/src/js_config.cpp new file mode 100644 index 00000000..0d2abf65 --- /dev/null +++ b/relational_store/frameworks/js/napi/cloud_data/src/js_config.cpp @@ -0,0 +1,221 @@ +/* +* Copyright (c) 2023 Huawei Device Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +#define LOG_TAG "JsConfig" +#include "js_config.h" + +#include "cloud_manager.h" +#include "js_error_utils.h" +#include "js_util.h" +#include "log_print.h" +#include "napi_queue.h" + +using namespace OHOS::CloudData; + +JsConfig::JsConfig() {} + +JsConfig::~JsConfig() {} + +/* + * [JS API Prototype] + * [AsyncCallback] + * enableCloud(accountId: string, switches: {[bundleName: string]: boolean}, callback: AsyncCallback): void; + * [Promise] + * enableCloud(accountId: string, switches: {[bundleName: string]: boolean}): Promise; + */ +napi_value JsConfig::EnableCloud(napi_env env, napi_callback_info info) +{ + struct EnableCloudContext : public ContextBase { + std::string accountId; + std::map switches1; + std::map switches2; + }; + auto ctxt = std::make_shared(); + ctxt->GetCbInfo(env, info, [env, ctxt](size_t argc, napi_value *argv) { + // required 2 arguments :: + ASSERT_BUSINESS_ERR(ctxt, argc >= 2, Status::INVALID_ARGUMENT, "The number of parameters is incorrect."); + ctxt->status = JSUtil::GetValue(env, argv[0], ctxt->accountId); + ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok, Status::INVALID_ARGUMENT, "The type of key must be string."); + ctxt->status = JSUtil::GetValue(env, argv[1], ctxt->switches1); + ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok, Status::INVALID_ARGUMENT, + "The type of key must be {[bundleName: string]: boolean}."); + for (auto item : ctxt->switches1) { + ctxt->switches2.insert(std::pair(item.first, static_cast(item.second))); + } + }); + + ASSERT_NULL(!ctxt->isThrowError, "EnableCloud exit"); + + auto execute = [ctxt]() { + auto proxy = CloudManager::GetInstance().GetCloudService(); + int32_t status = proxy->EnableCloud(ctxt->accountId, ctxt->switches2); + ZLOGD("EnableCloud return %{public}d", status); + ctxt->status = (GenerateNapiError(static_cast(status), ctxt->jsCode, ctxt->error) == Status::SUCCESS) + ? napi_ok + : napi_generic_failure; + }; + return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute); +} + +/* + * [JS API Prototype] + * [AsyncCallback] + * disableCloud(accountId: string, callback: AsyncCallback): void; + * [Promise] + * disableCloud(accountId: string): Promise; + */ +napi_value JsConfig::DisableCloud(napi_env env, napi_callback_info info) +{ + struct DisableCloudContext : public ContextBase { + std::string accountId; + }; + auto ctxt = std::make_shared(); + ctxt->GetCbInfo(env, info, [env, ctxt](size_t argc, napi_value *argv) { + // required 2 arguments :: + ASSERT_BUSINESS_ERR(ctxt, argc >= 1, Status::INVALID_ARGUMENT, "The number of parameters is incorrect."); + ctxt->status = JSUtil::GetValue(env, argv[0], ctxt->accountId); + ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok, Status::INVALID_ARGUMENT, + "The type of accountId must be string."); + }); + + ASSERT_NULL(!ctxt->isThrowError, "DisableCloud exit"); + + auto execute = [ctxt]() { + auto proxy = CloudManager::GetInstance().GetCloudService(); + int32_t status = proxy->DisableCloud(ctxt->accountId); + ZLOGD("DisableCloud return %{public}d", status); + ctxt->status = (GenerateNapiError(static_cast(status), ctxt->jsCode, ctxt->error) == Status::SUCCESS) + ? napi_ok + : napi_generic_failure; + }; + return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute); +} + +/* + * [JS API Prototype] + * [AsyncCallback] + * changeAppCloudSwitch(accountId: string, bundleName: string, status :boolean, callback: AsyncCallback): void; + * [Promise] + * changeAppCloudSwitch(accountId: string, bundleName: string, status :boolean): Promise; + */ +napi_value JsConfig::ChangeAppCloudSwitch(napi_env env, napi_callback_info info) +{ + struct ChangeAppSwitchContext : public ContextBase { + std::string accountId; + std::string bundleName; + bool status; + }; + auto ctxt = std::make_shared(); + ctxt->GetCbInfo(env, info, [env, ctxt](size_t argc, napi_value *argv) { + // required 3 arguments :: + ASSERT_BUSINESS_ERR(ctxt, argc >= 3, Status::INVALID_ARGUMENT, "The number of parameters is incorrect."); + ctxt->status = JSUtil::GetValue(env, argv[0], ctxt->accountId); + ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok, Status::INVALID_ARGUMENT, + "The type of accountId must be string."); + ctxt->status = JSUtil::GetValue(env, argv[1], ctxt->bundleName); + ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok, Status::INVALID_ARGUMENT, + "The type of bundleName must be string."); + ctxt->status = JSUtil::GetValue(env, argv[2], ctxt->status); + ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok, Status::INVALID_ARGUMENT, + "The type of bundleName must be boolean."); + }); + + ASSERT_NULL(!ctxt->isThrowError, "ChangeAppCloudSwitch exit"); + + auto execute = [ctxt]() { + auto proxy = CloudManager::GetInstance().GetCloudService(); + int32_t status = proxy->ChangeAppSwitch(ctxt->accountId, ctxt->bundleName, ctxt->status); + ZLOGD("kvStore->Put return %{public}d", status); + ctxt->status = (GenerateNapiError(static_cast(status), ctxt->jsCode, ctxt->error) == Status::SUCCESS) + ? napi_ok + : napi_generic_failure; + }; + return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute); +} + +/* + * [JS API Prototype] + * [AsyncCallback] + * clean(accountId: string, appActions: {[bundleName: string]: Action}, callback: AsyncCallback): void; + * [Promise] + * clean(accountId: string, appActions: {[bundleName: string]: Action}): Promise; + */ +napi_value JsConfig::Clean(napi_env env, napi_callback_info info) +{ + struct CleanContext : public ContextBase { + std::string accountId; + std::map actions; + }; + auto ctxt = std::make_shared(); + ctxt->GetCbInfo(env, info, [env, ctxt](size_t argc, napi_value *argv) { + // required 2 arguments :: + ASSERT_BUSINESS_ERR(ctxt, argc >= 2, Status::INVALID_ARGUMENT, "The number of parameters is incorrect."); + ctxt->status = JSUtil::GetValue(env, argv[0], ctxt->accountId); + ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok, Status::INVALID_ARGUMENT, + "The type of accountId must be string."); + ctxt->status = JSUtil::GetValue(env, argv[1], ctxt->actions); + ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok, Status::INVALID_ARGUMENT, + "The type of actions must be {[bundleName: string]: int32_t}."); + }); + + ASSERT_NULL(!ctxt->isThrowError, "Clean exit"); + + auto execute = [ctxt]() { + auto proxy = CloudManager::GetInstance().GetCloudService(); + int32_t status = proxy->Clean(ctxt->accountId, ctxt->actions); + ZLOGD("Clean return %{public}d", status); + ctxt->status = (GenerateNapiError(static_cast(status), ctxt->jsCode, ctxt->error) == Status::SUCCESS) + ? napi_ok + : napi_generic_failure; + }; + return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute); +} + +/* + * [JS API Prototype] + * [AsyncCallback] + * notifyDataChange(accountId: string, bundleName: string, callback: AsyncCallback): void; + * [Promise] + * notifyDataChange(accountId: string, bundleName: string): Promise; + */ +napi_value JsConfig::NotifyDataChange(napi_env env, napi_callback_info info) +{ + struct ChangeAppSwitchContext : public ContextBase { + std::string accountId; + std::string bundleName; + }; + auto ctxt = std::make_shared(); + ctxt->GetCbInfo(env, info, [env, ctxt](size_t argc, napi_value *argv) { + // required 2 arguments :: + ASSERT_BUSINESS_ERR(ctxt, argc >= 2, Status::INVALID_ARGUMENT, "The number of parameters is incorrect."); + ctxt->status = JSUtil::GetValue(env, argv[0], ctxt->accountId); + ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok, Status::INVALID_ARGUMENT, + "The type of accountId must be string."); + ctxt->status = JSUtil::GetValue(env, argv[1], ctxt->bundleName); + ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok, Status::INVALID_ARGUMENT, + "The type of bundleName must be string."); + }); + + ASSERT_NULL(!ctxt->isThrowError, "NotifyDataChange exit"); + + auto execute = [ctxt]() { + auto proxy = CloudManager::GetInstance().GetCloudService(); + int32_t status = proxy->NotifyDataChange(ctxt->accountId, ctxt->bundleName); + ZLOGD("NotifyDataChange return %{public}d", status); + ctxt->status = (GenerateNapiError(static_cast(status), ctxt->jsCode, ctxt->error) == Status::SUCCESS) + ? napi_ok + : napi_generic_failure; + }; + return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute); +} \ No newline at end of file diff --git a/relational_store/frameworks/js/napi/cloud_data/src/js_const_properties.cpp b/relational_store/frameworks/js/napi/cloud_data/src/js_const_properties.cpp new file mode 100644 index 00000000..60f4df42 --- /dev/null +++ b/relational_store/frameworks/js/napi/cloud_data/src/js_const_properties.cpp @@ -0,0 +1,53 @@ +/* +* Copyright (c) 2023 Huawei Device Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +#define LOG_TAG "Const_Properties" +#include "js_const_properties.h" + +#include "cloud_service.h" +#include "log_print.h" +#include "napi_queue.h" + +using Action = OHOS::CloudData::CloudService::Action; +namespace OHOS::CloudData { +static napi_status SetNamedProperty(napi_env env, napi_value &obj, const std::string &name, int32_t value) +{ + napi_value property = nullptr; + napi_status status = napi_create_int32(env, value, &property); + ASSERT(status == napi_ok, "int32_t to napi_value failed!", status); + status = napi_set_named_property(env, obj, name.c_str(), property); + ASSERT(status == napi_ok, "napi_set_named_property failed!", status); + return status; +} + +static napi_value ExportAction(napi_env env) +{ + napi_value action = nullptr; + napi_create_object(env, &action); + SetNamedProperty(env, action, "CLEAR_CLOUD_INFO", (int32_t)Action::CLEAR_CLOUD_INFO); + SetNamedProperty(env, action, "CLEAR_CLOUD_DATA_AND_INFO", (int32_t)Action::CLEAR_CLOUD_DATA_AND_INFO); + napi_object_freeze(env, action); + return action; +} + +napi_status InitConstProperties(napi_env env, napi_value exports) +{ + const napi_property_descriptor properties[] = { + DECLARE_NAPI_PROPERTY("Action", ExportAction(env)), + }; + size_t count = sizeof(properties) / sizeof(properties[0]); + + return napi_define_properties(env, exports, count, properties); +} +} // namespace OHOS::CloudData diff --git a/relational_store/frameworks/js/napi/cloud_data/src/js_error_utils.cpp b/relational_store/frameworks/js/napi/cloud_data/src/js_error_utils.cpp new file mode 100644 index 00000000..300c99ee --- /dev/null +++ b/relational_store/frameworks/js/napi/cloud_data/src/js_error_utils.cpp @@ -0,0 +1,91 @@ +/* +* Copyright (c) 2023 Huawei Device Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +#define LOG_TAG "JS_ERROR_UTILS" + +#include "js_error_utils.h" + +#include + +namespace OHOS::CloudData { +using JsErrorCode = OHOS::CloudData::JsErrorCode; + +static constexpr JsErrorCode JS_ERROR_CODE_MSGS[] = { + { Status::INVALID_ARGUMENT, 401, "Parameter error." }, +}; + +const std::optional GetJsErrorCode(int32_t errorCode) +{ + auto jsErrorCode = JsErrorCode{ errorCode, -1, "" }; + auto iter = std::lower_bound(JS_ERROR_CODE_MSGS, + JS_ERROR_CODE_MSGS + sizeof(JS_ERROR_CODE_MSGS) / sizeof(JS_ERROR_CODE_MSGS[0]), jsErrorCode, + [](const JsErrorCode &jsErrorCode1, const JsErrorCode &jsErrorCode2) { + return jsErrorCode1.status < jsErrorCode2.status; + }); + if (iter < JS_ERROR_CODE_MSGS + sizeof(JS_ERROR_CODE_MSGS) / sizeof(JS_ERROR_CODE_MSGS[0]) && + iter->status == errorCode) { + return *iter; + } + return std::nullopt; +} + +Status GenerateNapiError(Status status, int32_t &errCode, std::string &errMessage) +{ + auto errorMsg = GetJsErrorCode(status); + if (errorMsg.has_value()) { + auto napiError = errorMsg.value(); + errCode = napiError.jsCode; + errMessage = napiError.message; + } else { + // unmatched status return unified error code + errCode = -1; + errMessage = ""; + } + ZLOGD("GenerateNapiError errCode is %{public}d", errCode); + if (errCode == 0) { + return Status::SUCCESS; + } + return status; +} + +void ThrowNapiError(napi_env env, int32_t status, std::string errMessage, bool isParamsCheck) +{ + ZLOGD("ThrowNapiError message: %{public}s", errMessage.c_str()); + if (status == Status::SUCCESS) { + return; + } + auto errorMsg = GetJsErrorCode(status); + JsErrorCode napiError; + if (errorMsg.has_value()) { + napiError = errorMsg.value(); + } else { + napiError.jsCode = -1; + napiError.message = ""; + } + + std::string message(napiError.message); + if (isParamsCheck) { + napiError.jsCode = 401; + message += errMessage; + } + + std::string jsCode; + if (napiError.jsCode == -1) { + jsCode = ""; + } else { + jsCode = std::to_string(napiError.jsCode); + } + napi_throw_error(env, jsCode.c_str(), message.c_str()); +} +} // namespace OHOS::CloudData diff --git a/relational_store/frameworks/js/napi/cloud_data/src/js_util.cpp b/relational_store/frameworks/js/napi/cloud_data/src/js_util.cpp new file mode 100644 index 00000000..554e7ee2 --- /dev/null +++ b/relational_store/frameworks/js/napi/cloud_data/src/js_util.cpp @@ -0,0 +1,166 @@ +/* +* Copyright (c) 2023 Huawei Device Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +#define LOG_TAG "JSUtil" +#include "js_util.h" + +#include "log_print.h" +#include "napi_base_context.h" +#include "napi_queue.h" + +namespace OHOS::CloudData { +constexpr int32_t STR_MAX_LENGTH = 4096; +constexpr size_t STR_TAIL_LENGTH = 1; + +JSUtil::StatusMsg JSUtil::GetValue(napi_env env, napi_value in, napi_value &out) +{ + out = in; + return napi_ok; +} + +JSUtil::StatusMsg JSUtil::SetValue(napi_env env, napi_value in, napi_value &out) +{ + out = in; + return napi_ok; +} + +/* napi_value <-> bool */ +JSUtil::StatusMsg JSUtil::GetValue(napi_env env, napi_value in, bool &out) +{ + return napi_get_value_bool(env, in, &out); +} + +JSUtil::StatusMsg JSUtil::SetValue(napi_env env, const bool &in, napi_value &out) +{ + return napi_get_boolean(env, in, &out); +} + +/* napi_value <-> int32_t */ +napi_status JSUtil::GetValue(napi_env env, napi_value in, int32_t &out) +{ + return napi_get_value_int32(env, in, &out); +} + +napi_status JSUtil::SetValue(napi_env env, const int32_t &in, napi_value &out) +{ + return napi_create_int32(env, in, &out); +} + +/* napi_value <-> std::string */ +JSUtil::StatusMsg JSUtil::GetValue(napi_env env, napi_value in, std::string &out) +{ + napi_valuetype type = napi_undefined; + napi_status status = napi_typeof(env, in, &type); + ASSERT((status == napi_ok) && (type == napi_string), "invalid type", napi_invalid_arg); + + size_t maxLen = STR_MAX_LENGTH; + status = napi_get_value_string_utf8(env, in, NULL, 0, &maxLen); + if (maxLen <= 0) { + return status; + } + ZLOGD("napi_value -> std::string get length %{public}d", (int)maxLen); + char *buf = new (std::nothrow) char[maxLen + STR_TAIL_LENGTH]; + if (buf != nullptr) { + size_t len = 0; + status = napi_get_value_string_utf8(env, in, buf, maxLen + STR_TAIL_LENGTH, &len); + if (status == napi_ok) { + buf[len] = 0; + out = std::string(buf); + } + delete[] buf; + } else { + status = napi_generic_failure; + } + return status; +} + +JSUtil::StatusMsg JSUtil::SetValue(napi_env env, const std::string &in, napi_value &out) +{ + return napi_create_string_utf8(env, in.c_str(), in.size(), &out); +} + +/* napi_value <-> std::map */ +JSUtil::StatusMsg JSUtil::GetValue(napi_env env, napi_value in, std::map &out) +{ + ZLOGD("napi_value -> std::map "); + out.clear(); + uint32_t length = 0; + napi_status status = napi_get_array_length(env, in, &length); + ASSERT((status == napi_ok) && (length > 0), "get_map failed!", napi_invalid_arg); + for (uint32_t i = 0; i < length; ++i) { + napi_value item = nullptr; + status = napi_get_element(env, in, i, &item); + ASSERT((item != nullptr) && (status == napi_ok), "no element", napi_invalid_arg); + int index = 0; + napi_value item1 = nullptr; + status = napi_get_element(env, item, index++, &item1); + std::string key; + status = GetValue(env, item1, key); + napi_value item2 = nullptr; + status = napi_get_element(env, item, index, &item2); + bool value; + status = GetValue(env, item2, value); + out.insert(std::pair(key, status)); + } + return status; +} + +/* napi_value <-> std::map */ +JSUtil::StatusMsg JSUtil::GetValue(napi_env env, napi_value in, std::map &out) +{ + ZLOGD("napi_value -> std::map "); + out.clear(); + uint32_t length = 0; + napi_status status = napi_get_array_length(env, in, &length); + ASSERT((status == napi_ok) && (length > 0), "get_map failed!", napi_invalid_arg); + for (uint32_t i = 0; i < length; ++i) { + napi_value item = nullptr; + status = napi_get_element(env, in, i, &item); + ASSERT((item != nullptr) && (status == napi_ok), "no element", napi_invalid_arg); + int index = 0; + napi_value item1 = nullptr; + status = napi_get_element(env, item, index++, &item1); + std::string key; + status = GetValue(env, item1, key); + napi_value item2 = nullptr; + status = napi_get_element(env, item, index, &item2); + int32_t actionType; + status = GetValue(env, item2, actionType); + ASSERT(ValidSubscribeType(actionType) == true, "not action", napi_invalid_arg); + out.insert(std::pair(key, actionType)); + } + return status; +} + +JSUtil::StatusMsg JSUtil::SetValue(napi_env env, const std::map &in, napi_value &out) +{ + ZLOGD("napi_value <- std::map "); + napi_status status = napi_create_array_with_length(env, in.size(), &out); + ASSERT((status == napi_ok), "invalid object", status); + int index = 0; + for (const auto &[key, value] : in) { + napi_value element = nullptr; + napi_create_array_with_length(env, TUPLE_SIZE, &element); + napi_value jsKey = nullptr; + napi_create_string_utf8(env, key.c_str(), key.size(), &jsKey); + napi_set_element(env, element, TUPLE_KEY, jsKey); + napi_value jsValue = nullptr; + napi_create_int32(env, static_cast(value), &jsValue); + napi_set_element(env, element, TUPLE_VALUE, jsValue); + napi_set_element(env, out, index++, element); + } + return status; +} + +} // namespace OHOS::CloudData diff --git a/relational_store/frameworks/js/napi/cloud_data/src/napi_queue.cpp b/relational_store/frameworks/js/napi/cloud_data/src/napi_queue.cpp new file mode 100644 index 00000000..4db2a0ba --- /dev/null +++ b/relational_store/frameworks/js/napi/cloud_data/src/napi_queue.cpp @@ -0,0 +1,163 @@ +/* +* Copyright (c) 2023 Huawei Device Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +#define LOG_TAG "NapiQueue" +#include "napi_queue.h" + +namespace OHOS::CloudData { +ContextBase::~ContextBase() +{ + ZLOGD("no memory leak after callback or promise[resolved/rejected]"); + if (env != nullptr) { + if (callbackRef != nullptr) { + auto status = napi_delete_reference(env, callbackRef); + ZLOGD("status:%{public}d", status); + } + if (selfRef != nullptr) { + auto status = napi_delete_reference(env, selfRef); + ZLOGD("status:%{public}d", status); + } + env = nullptr; + } +} + +void ContextBase::GetCbInfo(napi_env envi, napi_callback_info info, NapiCbInfoParser parse, bool sync) +{ + env = envi; + size_t argc = ARGC_MAX; + napi_value argv[ARGC_MAX] = { nullptr }; + status = napi_get_cb_info(env, info, &argc, argv, &self, nullptr); + ASSERT_STATUS(this, "napi_get_cb_info failed!"); + ASSERT_ARGS(this, argc <= ARGC_MAX, "too many arguments!"); + ASSERT_ARGS(this, self != nullptr, "no JavaScript this argument!"); + if (!sync) { + napi_create_reference(env, self, 1, &selfRef); + } + status = napi_unwrap(env, self, &native); + ASSERT_STATUS(this, "self unwrap failed!"); + + if (!sync && (argc > 0)) { + // get the last arguments :: + size_t index = argc - 1; + napi_valuetype type = napi_undefined; + napi_status tyst = napi_typeof(env, argv[index], &type); + if ((tyst == napi_ok) && (type == napi_function)) { + status = napi_create_reference(env, argv[index], 1, &callbackRef); + ASSERT_STATUS(this, "ref callback failed!"); + argc = index; + ZLOGD("async callback, no promise"); + } else { + ZLOGD("no callback, async pormose"); + } + } + + if (parse) { + parse(argc, argv); + } else { + ASSERT_ARGS(this, argc == 0, "required no arguments!"); + } +} + +napi_value NapiQueue::AsyncWork(napi_env env, std::shared_ptr ctxt, const std::string &name, + NapiAsyncExecute execute, NapiAsyncComplete complete) +{ + ZLOGD("name=%{public}s", name.c_str()); + AsyncContext *aCtx = new AsyncContext; + aCtx->env = env; + aCtx->ctx = std::move(ctxt); + aCtx->execute = std::move(execute); + aCtx->complete = std::move(complete); + napi_value promise = nullptr; + if (aCtx->ctx->callbackRef == nullptr) { + napi_create_promise(env, &aCtx->deferred, &promise); + ZLOGD("create deferred promise"); + } else { + napi_get_undefined(env, &promise); + } + + napi_value resource = nullptr; + napi_create_string_utf8(env, name.c_str(), NAPI_AUTO_LENGTH, &resource); + napi_create_async_work( + env, nullptr, resource, + [](napi_env env, void *data) { + ASSERT_VOID(data != nullptr, "napi_async_execute_callback nullptr"); + auto actx = reinterpret_cast(data); + ZLOGD("napi_async_execute_callback ctxt->status=%{public}d", actx->ctx->status); + if (actx->execute && actx->ctx->status == napi_ok) { + actx->execute(); + } + }, + [](napi_env env, napi_status status, void *data) { + ASSERT_VOID(data != nullptr, "napi_async_complete_callback nullptr"); + auto actx = reinterpret_cast(data); + ZLOGD("napi_async_complete_callback status=%{public}d, ctxt->status=%{public}d", status, actx->ctx->status); + if ((status != napi_ok) && (actx->ctx->status == napi_ok)) { + actx->ctx->status = status; + } + napi_value output = nullptr; + if ((actx->complete) && (status == napi_ok) && (actx->ctx->status == napi_ok)) { + actx->complete(output); + } + GenerateOutput(*actx, output); + delete actx; + }, + reinterpret_cast(aCtx), &aCtx->work); + auto status = napi_queue_async_work(env, aCtx->work); + if (status != napi_ok) { + napi_get_undefined(env, &promise); + delete aCtx; + } + return promise; +} + +void NapiQueue::GenerateOutput(AsyncContext &ctx, napi_value output) +{ + napi_value result[RESULT_ALL] = { nullptr }; + if (ctx.ctx->status == napi_ok) { + napi_get_undefined(ctx.env, &result[RESULT_ERROR]); + if (output == nullptr) { + napi_get_undefined(ctx.env, &output); + } + result[RESULT_DATA] = output; + } else { + napi_value message = nullptr; + napi_value errorCode = nullptr; + if (ctx.ctx->jsCode != 0 && ctx.ctx->jsCode != -1) { + napi_create_string_utf8(ctx.env, std::to_string(ctx.ctx->jsCode).c_str(), NAPI_AUTO_LENGTH, &errorCode); + } + if (ctx.ctx->jsCode == -1) { + std::string jscode = ""; + napi_create_string_utf8(ctx.env, jscode.c_str(), NAPI_AUTO_LENGTH, &errorCode); + } + napi_create_string_utf8(ctx.env, ctx.ctx->error.c_str(), NAPI_AUTO_LENGTH, &message); + napi_create_error(ctx.env, errorCode, message, &result[RESULT_ERROR]); + napi_get_undefined(ctx.env, &result[RESULT_DATA]); + } + if (ctx.deferred != nullptr) { + if (ctx.ctx->status == napi_ok) { + ZLOGD("deferred promise resolved"); + napi_resolve_deferred(ctx.env, ctx.deferred, result[RESULT_DATA]); + } else { + ZLOGD("deferred promise rejected"); + napi_reject_deferred(ctx.env, ctx.deferred, result[RESULT_ERROR]); + } + } else { + napi_value callback = nullptr; + napi_get_reference_value(ctx.env, ctx.ctx->callbackRef, &callback); + napi_value callbackResult = nullptr; + ZLOGD("call callback function"); + napi_call_function(ctx.env, nullptr, callback, RESULT_ALL, result, &callbackResult); + } +} +} // namespace OHOS::CloudData -- Gitee