diff --git a/frameworks/libs/distributeddb/BUILD.gn b/frameworks/libs/distributeddb/BUILD.gn index c0fea4f3ae7c9ba3dad5bb31247a717196dd2a81..b85586a8d069b5d7c08e0c463e123c7120a7fa92 100644 --- a/frameworks/libs/distributeddb/BUILD.gn +++ b/frameworks/libs/distributeddb/BUILD.gn @@ -217,6 +217,7 @@ config("distributeddb_client_config") { "storage/src/kv", "syncer/src", "syncer/src/device", + "storage/src/gaussdb_rd", "storage/src/sqlite/relational", "storage/src/relational", ] diff --git a/frameworks/libs/distributeddb/common/include/db_constant.h b/frameworks/libs/distributeddb/common/include/db_constant.h index a0c15ad39f2f3e6fa627757820cefeb70fda8664..b2f37d3fc1856754fa4087569675c59f3767441d 100644 --- a/frameworks/libs/distributeddb/common/include/db_constant.h +++ b/frameworks/libs/distributeddb/common/include/db_constant.h @@ -119,6 +119,9 @@ public: static constexpr const char *UPDATE_META_FUNC = "update_meta_within_trigger"; + static constexpr const char *REGEXP_MATCH_FUNC = "REGEXP_MATCH"; + static constexpr const char *IS_ENTITY_DUPLICATE_FUNC = "is_entity_duplicate"; + // Prefix Key in meta db static constexpr const char *DEVICEID_PREFIX_KEY = "deviceId"; static constexpr const char *USERID_PREFIX_KEY = "userId"; diff --git a/frameworks/libs/distributeddb/distributeddb.gni b/frameworks/libs/distributeddb/distributeddb.gni index 958f5237c32f82702073031672ef7bee7ba76c02..111731f9f25369e2709065d9a32978c8c352bba0 100755 --- a/frameworks/libs/distributeddb/distributeddb.gni +++ b/frameworks/libs/distributeddb/distributeddb.gni @@ -110,6 +110,8 @@ distributeddb_src = [ "${distributeddb_path}/storage/src/db_properties.cpp", "${distributeddb_path}/storage/src/default_factory.cpp", "${distributeddb_path}/storage/src/single_ver_utils.cpp", + "${distributeddb_path}/storage/src/gaussdb_rd/gspd_api_manager.cpp", + "${distributeddb_path}/storage/src/gaussdb_rd/gspd_process_api.cpp", "${distributeddb_path}/storage/src/gaussdb_rd/rd_single_ver_result_set.cpp", "${distributeddb_path}/storage/src/gaussdb_rd/rd_single_ver_natural_store_connection.cpp", "${distributeddb_path}/storage/src/gaussdb_rd/rd_single_ver_natural_store.cpp", @@ -332,6 +334,8 @@ distributeddb_base_src = [ "${distributeddb_path}/interfaces/src/relational/relational_store_manager_client.cpp", "${distributeddb_path}/interfaces/src/kv_store_errno.cpp", "${distributeddb_path}/storage/src/cloud/cloud_storage_utils_client.cpp", + "${distributeddb_path}/storage/src/gaussdb_rd/gspd_api_manager.cpp", + "${distributeddb_path}/storage/src/gaussdb_rd/gspd_process_api.cpp", "${distributeddb_path}/storage/src/sqlite/relational/cloud_sync_log_table_manager.cpp", "${distributeddb_path}/storage/src/sqlite/relational/knowledge_log_table_manager.cpp", "${distributeddb_path}/storage/src/sqlite/relational/simple_tracker_log_table_manager.cpp", @@ -343,8 +347,6 @@ distributeddb_base_src = [ ] distributeddb_client_src = [ - "${distributeddb_path}/interfaces/src/relational/gspd_api_manager.cpp", - "${distributeddb_path}/interfaces/src/relational/gspd_process_api.cpp", "${distributeddb_path}/interfaces/src/relational/knowledge_source_utils.cpp", "${distributeddb_path}/interfaces/src/relational/preprocess_entity_ext.cpp", "${distributeddb_path}/interfaces/src/relational/relational_store_sqlite_ext.cpp", diff --git a/frameworks/libs/distributeddb/interfaces/src/relational/gspd_api_manager.cpp b/frameworks/libs/distributeddb/storage/src/gaussdb_rd/gspd_api_manager.cpp similarity index 100% rename from frameworks/libs/distributeddb/interfaces/src/relational/gspd_api_manager.cpp rename to frameworks/libs/distributeddb/storage/src/gaussdb_rd/gspd_api_manager.cpp diff --git a/frameworks/libs/distributeddb/interfaces/src/relational/gspd_api_manager.h b/frameworks/libs/distributeddb/storage/src/gaussdb_rd/gspd_api_manager.h similarity index 100% rename from frameworks/libs/distributeddb/interfaces/src/relational/gspd_api_manager.h rename to frameworks/libs/distributeddb/storage/src/gaussdb_rd/gspd_api_manager.h diff --git a/frameworks/libs/distributeddb/interfaces/src/relational/gspd_dataflow_error.h b/frameworks/libs/distributeddb/storage/src/gaussdb_rd/gspd_dataflow_error.h similarity index 100% rename from frameworks/libs/distributeddb/interfaces/src/relational/gspd_dataflow_error.h rename to frameworks/libs/distributeddb/storage/src/gaussdb_rd/gspd_dataflow_error.h diff --git a/frameworks/libs/distributeddb/interfaces/src/relational/gspd_process_api.cpp b/frameworks/libs/distributeddb/storage/src/gaussdb_rd/gspd_process_api.cpp similarity index 98% rename from frameworks/libs/distributeddb/interfaces/src/relational/gspd_process_api.cpp rename to frameworks/libs/distributeddb/storage/src/gaussdb_rd/gspd_process_api.cpp index 9c6460d3dcb49e60f491260d3bb55b5f586a26d1..0a200f8c5f92b8de44b8370d7a255dea41e70459 100644 --- a/frameworks/libs/distributeddb/interfaces/src/relational/gspd_process_api.cpp +++ b/frameworks/libs/distributeddb/storage/src/gaussdb_rd/gspd_process_api.cpp @@ -52,6 +52,7 @@ static GSPD_APIInfo *g_gspdApiInfo = GetApiInfo(); int32_t GSPD_IsEntityDuplicate(const char *queryJson, const char *dbJson, bool *isDuplicate) { +#ifndef _WIN32 GetApiInfoInstance(); if (g_gspdApiInfo->isEntityDuplicateApi == nullptr) { const char *error = dlerror(); @@ -66,6 +67,8 @@ int32_t GSPD_IsEntityDuplicate(const char *queryJson, const char *dbJson, bool * } UnloadApiInfo(g_gspdApiInfo); return TransferGspdErrno(ret); +#endif + return E_OK; } } // namespace DistributedDB diff --git a/frameworks/libs/distributeddb/interfaces/src/relational/gspd_process_api.h b/frameworks/libs/distributeddb/storage/src/gaussdb_rd/gspd_process_api.h similarity index 100% rename from frameworks/libs/distributeddb/interfaces/src/relational/gspd_process_api.h rename to frameworks/libs/distributeddb/storage/src/gaussdb_rd/gspd_process_api.h diff --git a/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_relational_storage_engine.cpp b/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_relational_storage_engine.cpp index 95b514da9b2ced31891f84568bd2c5b4dd573ce0..23fa05799e291ba7063e518478e494b395682fb3 100644 --- a/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_relational_storage_engine.cpp +++ b/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_relational_storage_engine.cpp @@ -87,6 +87,16 @@ int SQLiteSingleRelationalStorageEngine::RegisterFunction(sqlite3 *db) const LOGE("[engine] register cloud server observer failed!"); } + errCode = SQLiteUtils::RegisterRegexpMatchFunction(db); + if (errCode != E_OK) { + LOGE("[engine] register regexp match failed!"); + } + + errCode = SQLiteUtils::RegisterIsEntityDuplicateFunction(db); + if (errCode != E_OK) { + LOGE("[engine] register is_entity_duplicate match failed!"); + } + return errCode; } diff --git a/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_utils.cpp b/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_utils.cpp index 29e3e13258f1ed43799a92b15dd24809484b760f..414d79b4d0f359a8d043cefa92f9ba0d0a1f3887 100644 --- a/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_utils.cpp +++ b/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_utils.cpp @@ -1283,4 +1283,27 @@ int SQLiteUtils::RegisterMetaDataUpdateFunction(sqlite3 *db) } return SQLiteUtils::MapSQLiteErrno(errCode); } + +int SQLiteUtils::RegisterRegexpMatchFunction(sqlite3 *db) +{ + int errCode = sqlite3_create_function_v2(db, DBConstant::REGEXP_MATCH_FUNC, + 2, // 2: argc for register function + SQLITE_UTF8 | SQLITE_DETERMINISTIC, db, &SQLiteUtils::RegexpMatch, nullptr, nullptr, nullptr); + if (errCode != SQLITE_OK) { + LOGE("sqlite3_create_function_v2 about regexp match returned %d", errCode); + } + return SQLiteUtils::MapSQLiteErrno(errCode); +} + +int SQLiteUtils::RegisterIsEntityDuplicateFunction(sqlite3 *db) +{ + int errCode = sqlite3_create_function_v2(db, DBConstant::IS_ENTITY_DUPLICATE_FUNC, + 2, // 2: argc for register function + SQLITE_UTF8 | SQLITE_DETERMINISTIC, db, &SQLiteUtils::IsEntityDuplicate, nullptr, nullptr, nullptr); + if (errCode != SQLITE_OK) { + LOGE("sqlite3_create_function_v2 about Is Entity Duplicate match returned %d", errCode); + } + return SQLiteUtils::MapSQLiteErrno(errCode); +} + } // namespace DistributedDB diff --git a/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_utils.h b/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_utils.h index 6138adde9d0a164ed808364d8ed37ec35c53465d..336462ad074292d5fffbf3e4c5b14d270faba318 100644 --- a/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_utils.h +++ b/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_utils.h @@ -133,6 +133,10 @@ public: static int RegisterMetaDataUpdateFunction(sqlite3 *db); + static int RegisterRegexpMatchFunction(sqlite3 *db); + + static int RegisterIsEntityDuplicateFunction(sqlite3 *db); + static int GetDbSize(const std::string &dir, const std::string &dbName, uint64_t &size); static int AttachNewDatabase(sqlite3 *db, CipherType type, const CipherPassword &password, @@ -237,6 +241,8 @@ private: static void CalcHashKey(sqlite3_context *ctx, int argc, sqlite3_value **argv); static void CalcHash(sqlite3_context *ctx, int argc, sqlite3_value **argv); + static void RegexpMatch(sqlite3_context *ctx, int argc, sqlite3_value **argv); + static void IsEntityDuplicate(sqlite3_context *ctx, int argc, sqlite3_value **argv); static void GetSysTime(sqlite3_context *ctx, int argc, sqlite3_value **argv); static void GetLastTime(sqlite3_context *ctx, int argc, sqlite3_value **argv); diff --git a/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_utils_extend.cpp b/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_utils_extend.cpp index 8d73232dd5bb5bafb58f635b00a6b547feb8e708..22cc0a546ead05bb6351808e5f3351c1e2f0da96 100644 --- a/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_utils_extend.cpp +++ b/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_utils_extend.cpp @@ -22,12 +22,14 @@ #include #include #include +#include #include "sqlite_import.h" #include "securec.h" #include "db_constant.h" #include "db_common.h" #include "db_errno.h" +#include "gspd_process_api.h" #include "log_print.h" #include "value_object.h" #include "schema_utils.h" @@ -341,6 +343,53 @@ void SQLiteUtils::CalcHash(sqlite3_context *ctx, int argc, sqlite3_value **argv) CalcHashFunc(ctx, argv); } +void SQLiteUtils::RegexpMatch(sqlite3_context *ctx, int argc, sqlite3_value **argv) +{ + if (argc != 2) { // 2 is params count + sqlite3_result_error(ctx, "RegexpMatch requires 2 arguments: regex, string", -1); + return; + } + const char* regexStr = reinterpret_cast(sqlite3_value_text(argv[0])); + const char* textStr = reinterpret_cast(sqlite3_value_text(argv[1])); + if (regexStr == nullptr || textStr == nullptr) { + sqlite3_result_null(ctx); + return; + } + bool match = 0; + match = std::regex_match(textStr, std::regex(regexStr)); + sqlite3_result_int(ctx, match ? 1 : 0); // 1 found 0, not found +} + +void SQLiteUtils::IsEntityDuplicate(sqlite3_context *ctx, int argc, sqlite3_value **argv) +{ + if (ctx == nullptr) { + return; + } + + if (argc != 2 || argv == nullptr || argv[0] == nullptr || argv[1] == nullptr) { // 2 params count + std::string errorMsg = "is_entity_duplicate expects 2 arguments: entity_json, input_entity_json"; + sqlite3_result_error(ctx, errorMsg.c_str(), -1); + LOGE("%s", errorMsg.c_str()); + return; + } + + const char* dbEntityJson = reinterpret_cast(sqlite3_value_text(argv[0])); + const char* inputEntityJson = reinterpret_cast(sqlite3_value_text(argv[1])); + if (!dbEntityJson || !inputEntityJson) { + std::string errorMsg = "is_entity_duplicate expects not null value"; + return; + } + + bool isDuplicate = false; + int32_t ret = GSPD_IsEntityDuplicate(inputEntityJson, dbEntityJson, &isDuplicate); + if (ret != E_OK) { + LOGE("is_entity_duplicate call failed"); + sqlite3_result_error(ctx, "is_entity_duplicate call failed", -1); + return; + } + + sqlite3_result_int(ctx, isDuplicate ? 1 : 0); +} int SQLiteUtils::GetDbSize(const std::string &dir, const std::string &dbName, uint64_t &size) { diff --git a/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_relational_get_data_test.cpp b/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_relational_get_data_test.cpp index 99382c950194336018ab020be5ea190725f3e9e1..127e4d688eec0d92b389e654887513c86663f9b8 100644 --- a/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_relational_get_data_test.cpp +++ b/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_relational_get_data_test.cpp @@ -1835,5 +1835,26 @@ HWTEST_F(DistributedDBRelationalGetDataTest, AbnormalSyncerProxyTest001, TestSiz EXPECT_EQ(syncer.GetTaskCount(), 0); EXPECT_EQ(syncer.ExchangeClosePending(true), false); } + +/** + * @tc.name: RegexpMatchExample001 + * @tc.desc: Test relational support regexp_match. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zengchuanrui + */ +HWTEST_F(DistributedDBRelationalGetDataTest, RegexpMatchExample001, TestSize.Level1) +{ + ASSERT_EQ(g_mgr.OpenStore(g_storePath, g_storeID, RelationalStoreDelegate::Option {}, g_delegate), DBStatus::OK); + ASSERT_NE(g_delegate, nullptr); + + SqlCondition condition; + condition.sql = "SELECT REGEXP_MATCH('a', 'a') = TRUE"; + condition.readOnly = true; + + std::vector records; + EXPECT_EQ(g_delegate->ExecuteSql(condition, records), E_OK); + EXPECT_EQ(records.size(), 1); +} } #endif