diff --git a/frameworks/libs/distributeddb/common/src/relational/table_info.cpp b/frameworks/libs/distributeddb/common/src/relational/table_info.cpp index 99f9ce13845f91c8bdf3f7738e639ac65e151996..7e583f7d2dfb4f71ce87e8dd1039ce16ff0eae8f 100644 --- a/frameworks/libs/distributeddb/common/src/relational/table_info.cpp +++ b/frameworks/libs/distributeddb/common/src/relational/table_info.cpp @@ -806,6 +806,9 @@ int TableInfo::CheckTrackerTable() return -E_SCHEMA_MISMATCH; } } + if (trackerTable_.GetExtendNames().empty()) { + LOGW("[%s [%zu]] extend col not set.", tableName.c_str(), nameLength); + } for (const auto &colName : trackerTable_.GetExtendNames()) { if (colName.empty()) { LOGE("[%s [%zu]] extend col cannot be empty.", tableName.c_str(), nameLength); diff --git a/frameworks/libs/distributeddb/common/src/relational/tracker_table.cpp b/frameworks/libs/distributeddb/common/src/relational/tracker_table.cpp index d5b2c5468cf5723c36791eba8903fcac197482cb..3277b434c947da3a0aa73913c93dce979cd151a7 100644 --- a/frameworks/libs/distributeddb/common/src/relational/tracker_table.cpp +++ b/frameworks/libs/distributeddb/common/src/relational/tracker_table.cpp @@ -50,7 +50,7 @@ bool IsInvalidExtendColNames(const std::set &extendColNames) const std::string GetJsonAssignValSql(bool isDelete, const std::set &extendColNames) { if (extendColNames.empty()) { - return "''"; + return "'{}'"; } std::string newOrOld = isDelete ? "OLD." : "NEW."; std::string sql = "json_object("; @@ -67,7 +67,7 @@ const std::string TrackerTable::GetAssignValSql(bool isDelete) const if (!extendColNames_.empty() && !IsInvalidExtendColNames(extendColNames_)) { return GetJsonAssignValSql(isDelete, extendColNames_); } - return "''"; + return "'{}'"; } const std::string TrackerTable::GetExtendAssignValSql(bool isDelete) const diff --git a/frameworks/libs/distributeddb/interfaces/src/relational/relational_store_sqlite_ext.cpp b/frameworks/libs/distributeddb/interfaces/src/relational/relational_store_sqlite_ext.cpp index e1f0b50d0d2aed36340f1a75537199ce7ccc582d..8e4882c404b3b3a8607f6039c0f95629ee577d5f 100644 --- a/frameworks/libs/distributeddb/interfaces/src/relational/relational_store_sqlite_ext.cpp +++ b/frameworks/libs/distributeddb/interfaces/src/relational/relational_store_sqlite_ext.cpp @@ -434,9 +434,6 @@ std::map>> g_storeObserver std::mutex g_storeChangedDataMutex; std::map> g_storeChangedDataMap; -std::mutex g_clientCreateTableMutex; -std::set g_clientCreateTable; - std::mutex g_registerSqliteHookMutex; std::mutex g_createTempTriggerMutex; @@ -964,17 +961,25 @@ int GetTriggerSqls(sqlite3 *db, const std::map &tableInfos, s return E_OK; } -int AuthorizerCallback([[gnu::unused]] void *data, int operation, const char *tableNameChar, const char *, const char *, - const char *) +int TraceCallback(uint32_t traceType, void *traceData, void *stmt, void*) { - if (operation != SQLITE_CREATE_TABLE || tableNameChar == nullptr) { + if (traceType != SQLITE_TRACE_PROFILE || traceData == nullptr || stmt == nullptr) { return SQLITE_OK; } - std::lock_guard clientCreateTableLock(g_clientCreateTableMutex); - std::string tableName = static_cast(tableNameChar); - if (ParamCheckUtils::CheckRelationalTableName(tableName) && tableName.find("sqlite_") != 0 && - tableName.find("naturalbase_") != 0) { - g_clientCreateTable.insert(tableName); + auto statement = static_cast(stmt); + const char *sql = sqlite3_sql(statement); + if (sql == nullptr) { + return SQLITE_OK; + } + std::string sqlStr(sql); + std::transform(sqlStr.begin(), sqlStr.end(), sqlStr.begin(), ::tolower); + if (sqlStr.find("create table ") == std::string::npos) { + return SQLITE_OK; + } + auto db = static_cast(traceData); + int errCode = CreateDataChangeTempTrigger(db); + if (errCode != OK) { + LOGE("Create temp data change trigger failed after create table: %d", errCode); } return SQLITE_OK; } @@ -1029,34 +1034,6 @@ void StoreObserverCallback(sqlite3 *db, const std::string &hashFileName) } } TriggerObserver(storeObserver, hashFileName); - std::map tableInfos; - { - std::lock_guard clientCreateTableLock(g_clientCreateTableMutex); - if (g_clientCreateTable.empty()) { - return; - } - for (const auto &tableName : g_clientCreateTable) { - bool isRowid = true; - std::string type = ""; - JudgeIfGetRowid(db, tableName, type, isRowid); - tableInfos.insert(std::make_pair(tableName, isRowid)); - } - g_clientCreateTable.clear(); - } - std::vector triggerSqls; - int errCode = GetTriggerSqls(db, tableInfos, triggerSqls); - if (errCode != E_OK) { - LOGE("Get data change trigger sql failed %d", errCode); - return; - } - for (const auto &sql : triggerSqls) { - errCode = SQLiteUtils::ExecuteRawSQL(db, sql); - if (errCode != E_OK) { - LOGE("Create data change trigger failed %d", errCode); - return; - } - } - return; } int LogCommitHookCallback(void *data, sqlite3 *db, const char *zDb, int size) @@ -1138,7 +1115,7 @@ int RegisterDataChangeObserver(sqlite3 *db) void RegisterCommitAndRollbackHook(sqlite3 *db) { - sqlite3_set_authorizer(db, AuthorizerCallback, nullptr); + sqlite3_trace_v2(db, SQLITE_TRACE_PROFILE, TraceCallback, (void*)db); } int ResetStatement(sqlite3_stmt *&stmt) @@ -1665,7 +1642,6 @@ void PostHandle(bool isExists, sqlite3 *db) RegisterGetRawSysTime(db); RegisterCloudDataChangeObserver(db); RegisterDataChangeObserver(db); - RegisterCommitAndRollbackHook(db); (void)sqlite3_set_droptable_handle(db, &ClearTheLogAfterDropTable); (void)sqlite3_busy_timeout(db, BUSY_TIMEOUT); std::string recursiveTrigger = "PRAGMA recursive_triggers = ON;"; @@ -1913,6 +1889,8 @@ DB_API DistributedDB::DBStatus RegisterStoreObserver(sqlite3 *db, const std::sha return DistributedDB::DB_ERROR; } + RegisterCommitAndRollbackHook(db); + std::lock_guard lock(g_storeObserverMutex); if (std::find(g_storeObserverMap[hashFileName].begin(), g_storeObserverMap[hashFileName].end(), storeObserver) != g_storeObserverMap[hashFileName].end()) { diff --git a/frameworks/libs/distributeddb/storage/src/sqlite/relational/cloud_sync_log_table_manager.cpp b/frameworks/libs/distributeddb/storage/src/sqlite/relational/cloud_sync_log_table_manager.cpp index f58feb79f0dc9048ade1d2eb1a50a28fcce8be27..7d5c447e3a19cbb6a3f519591a0da3668a8c5791 100644 --- a/frameworks/libs/distributeddb/storage/src/sqlite/relational/cloud_sync_log_table_manager.cpp +++ b/frameworks/libs/distributeddb/storage/src/sqlite/relational/cloud_sync_log_table_manager.cpp @@ -209,7 +209,7 @@ std::vector CloudSyncLogTableManager::GetDropTriggers(const TableIn dropTriggers.emplace_back(updateTrigger); dropTriggers.emplace_back(deleteTrigger); if (table.GetTrackerTable().IsEmpty()) { - std::string clearExtendSql = "UPDATE " + GetLogTableName(table) + " SET extend_field = '';"; + std::string clearExtendSql = "UPDATE " + GetLogTableName(table) + " SET extend_field = '{}';"; dropTriggers.emplace_back(clearExtendSql); } return dropTriggers; diff --git a/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_utils_client.cpp b/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_utils_client.cpp index ecd4464ab59eaa93f3dea7eb00899c7b1534e78d..d56bbecefd7e3acbe658c3dbee1ebed1fecda678 100644 --- a/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_utils_client.cpp +++ b/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_utils_client.cpp @@ -215,7 +215,7 @@ std::string SQLiteRelationalUtils::GetExtendValue(const TrackerTable &trackerTab extendValue.pop_back(); extendValue += ")"; } else { - extendValue = "''"; + extendValue = "'{}'"; } return extendValue; } diff --git a/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_ver_relational_storage_executor.cpp b/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_ver_relational_storage_executor.cpp index 8fa74fa878bd7ce713a67618626680ddf31d685d..fd2d12315ea2edc3b3242df018fb5e49f50c28a8 100644 --- a/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_ver_relational_storage_executor.cpp +++ b/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_ver_relational_storage_executor.cpp @@ -201,7 +201,7 @@ int SQLiteSingleVerRelationalStorageExecutor::UpdateTrackerTable(sqlite3 *db, co std::string calPrimaryKeyHash = logMgrPtr->CalcPrimaryKeyHash("a.", tableInfo, identity); std::string sql = "INSERT OR REPLACE INTO " + logTable + " SELECT " + rowid + ", '', '', " + currentLocalTimeStr + " + " + rowid + ", " + currentLocalTimeStr + " + " + rowid + ", " + flag + ", " + calPrimaryKeyHash + - ", '', '', '', '', '', 0 FROM '" + tableName + "' AS a WHERE 1=1;"; + ", '', '{}', '', '', '', 0 FROM '" + tableName + "' AS a WHERE 1=1;"; errCode = trackerTable.ReBuildTempTrigger(db, TriggerMode::TriggerModeEnum::INSERT, [db, &sql]() { int ret = SQLiteUtils::ExecuteRawSQL(db, sql); if (ret != E_OK) { diff --git a/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_ver_relational_storage_extend_executor.cpp b/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_ver_relational_storage_extend_executor.cpp index dad090304caaadf71596fefcf069c0e9b71a90c8..6d67e5a4df82235b522468906941a948797201f6 100644 --- a/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_ver_relational_storage_extend_executor.cpp +++ b/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_ver_relational_storage_extend_executor.cpp @@ -2049,7 +2049,8 @@ void SQLiteSingleVerRelationalStorageExecutor::RecoverNullExtendLog(const Tracke return; } std::string sql = "SELECT COUNT(1) FROM " + DBCommon::GetLogTableName(trackerSchema.tableName) + - " WHERE (json_valid(extend_field) = 0 OR json_type(extend_field) IS NOT 'object') AND data_key != -1"; + " WHERE (json_valid(extend_field) = 0 OR json_type(extend_field) IS NOT 'object' OR" + + " json_extract(extend_field, '$') = '{}') AND data_key != -1"; if (!SQLiteRelationalUtils::ExecuteCheckSql(dbHandle_, sql).second) { return; } @@ -2083,7 +2084,8 @@ int SQLiteSingleVerRelationalStorageExecutor::RecoverNullExtendLogInner(const Tr }); actions.emplace_back([this, &trackerSchema]() { return UpdateExtendField(trackerSchema.tableName, trackerSchema.extendColNames, - " AND (json_valid(log.extend_field) = 0 OR json_type(log.extend_field) IS NOT 'object')"); + " AND (json_valid(log.extend_field) = 0 OR json_type(log.extend_field) IS NOT 'object' OR" + " json_extract(extend_field, '$') = '{}')"); }); actions.emplace_back([this]() { return ClearAllTempSyncTrigger(); diff --git a/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_cloud_interfaces_relational_ext_test.cpp b/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_cloud_interfaces_relational_ext_test.cpp index 377d475d5c56b26b975fd9a3ed493fa041c0cd54..2d2baeb308262e20fc04412b346b2ec8405f6021 100644 --- a/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_cloud_interfaces_relational_ext_test.cpp +++ b/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_cloud_interfaces_relational_ext_test.cpp @@ -1742,6 +1742,47 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, RegisterStoreObserverTes EXPECT_EQ(sqlite3_close_v2(db), SQLITE_OK); } +/** + * @tc.name: RegisterStoreObserverTest008 + * @tc.desc: Test store observer in transaction + * @tc.type: FUNC + * @tc.require: + * @tc.author: liaoyonghuang + */ +HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, RegisterStoreObserverTest008, TestSize.Level1) +{ + /** + * @tc.steps:step1. prepare db. + * @tc.expected: step1. return ok. + */ + sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX); + EXPECT_NE(db, nullptr); + auto storeObserver = std::make_shared(); + EXPECT_EQ(RegisterStoreObserver(db, storeObserver), OK); + RegisterDbHook(db); + EXPECT_EQ(RelationalTestUtils::ExecSql(db, "PRAGMA journal_mode=WAL;"), SQLITE_OK); + /** + * @tc.steps:step2. create tables and insert data in transaction. + * @tc.expected: step2. return ok. + */ + g_changedData.clear(); + EXPECT_EQ(RelationalTestUtils::ExecSql(db, "begin;"), SQLITE_OK); + std::string tableName = "primary_test"; + CreateTableForStoreObserver(db, tableName); + uint32_t dataCounts = 10; // 10 is count of insert options. + for (uint32_t i = 0; i < dataCounts; i++) { + std::string sql = "insert into " + tableName + " VALUES(" + std::to_string(i + 1) + ", 'zhangsan" + + std::to_string(i + 1) + "');"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); + } + EXPECT_EQ(RelationalTestUtils::ExecSql(db, "commit;"), SQLITE_OK); + std::this_thread::sleep_for(std::chrono::milliseconds(WAIT_TIME)); + ASSERT_EQ(g_changedData.size(), 1u); // 1 table insert data + EXPECT_EQ(g_changedData.front().tableName, tableName); + ASSERT_EQ(g_changedData.front().primaryData[OP_INSERT].size(), dataCounts); + EXPECT_EQ(sqlite3_close_v2(db), SQLITE_OK); +} + /** * @tc.name: AbnormalDelegateImplTest001 * @tc.desc: Test delegateImpl interface after delegate is closed diff --git a/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_relational_test.cpp b/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_relational_test.cpp index c89e04dbb7abd7c5d280d51157316c042bbaf2e0..73468efac24acfd418fec9b3c87f6292c5e1dea5 100644 --- a/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_relational_test.cpp +++ b/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_relational_test.cpp @@ -2102,7 +2102,7 @@ HWTEST_F(DistributedDBInterfacesRelationalTest, CreateDistributedTableTest007, T int64_t actualStatus = sqlite3_column_int64(stmt, 3); // index 3 is status EXPECT_EQ(actualFlag, static_cast(LogInfoFlag::FLAG_LOCAL) | static_cast(LogInfoFlag::FLAG_DEVICE_CLOUD_INCONSISTENCY)); - EXPECT_EQ(actualExtendVal, ""); + EXPECT_EQ(actualExtendVal, "{}"); EXPECT_EQ(actualCursor, actualCount); EXPECT_EQ(actualStatus, 0); } diff --git a/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_relational_tracker_table_test.cpp b/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_relational_tracker_table_test.cpp index a8da478f2ef517352492cb87474ba7046ae7be98..9ed60327687ed21549e10a2c3d328edaac7b44cb 100644 --- a/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_relational_tracker_table_test.cpp +++ b/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_relational_tracker_table_test.cpp @@ -1163,7 +1163,7 @@ HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest020, * @tc.expected: step3. Return OK. */ sql = "select count(*) from " + DBCommon::GetLogTableName(TABLE_NAME2) + - " where extend_field is NULL " + " AND cursor is NULL"; + " where extend_field is NULL OR cursor is NULL OR json_extract(extend_field, '$') = '{}'"; EXPECT_EQ(sqlite3_exec(g_db, sql.c_str(), CloudDBSyncUtilsTest::QueryCountCallback, reinterpret_cast(0), nullptr), SQLITE_OK); @@ -1174,7 +1174,7 @@ HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest020, schema.extendColNames = {EXTEND_COL_NAME3}; EXPECT_EQ(g_delegate->SetTrackerTable(schema), OK); sql = "select count(*) from " + std::string(DBConstant::RELATIONAL_PREFIX) + TABLE_NAME2 + - "_log where extend_field is NULL " + " AND cursor is NULL"; + "_log where extend_field is NULL OR cursor is NULL OR json_extract(extend_field, '$') = '{}'"; EXPECT_EQ(sqlite3_exec(g_db, sql.c_str(), CloudDBSyncUtilsTest::QueryCountCallback, reinterpret_cast(0), nullptr), SQLITE_OK); CloseStore(); diff --git a/frameworks/libs/distributeddb/test/unittest/common/store_test/rdb/distributeddb_rdb_upgrade_test.cpp b/frameworks/libs/distributeddb/test/unittest/common/store_test/rdb/distributeddb_rdb_upgrade_test.cpp index f3c51b4034b7cb213c9b1818a7448ce0db18993c..e19bad402c43cd3798d6fd2b143eca0d6b2df993 100644 --- a/frameworks/libs/distributeddb/test/unittest/common/store_test/rdb/distributeddb_rdb_upgrade_test.cpp +++ b/frameworks/libs/distributeddb/test/unittest/common/store_test/rdb/distributeddb_rdb_upgrade_test.cpp @@ -132,17 +132,53 @@ HWTEST_F(DistributedDBRDBUpgradeTest, UpgradeTracker002, TestSize.Level0) * @tc.steps: step2. Insert local data and log update extend_field to empty str. * @tc.expected: step2. Ok */ - InsertLocalDBData(0, 1, info1); + int chkCnt = 10; + InsertLocalDBData(0, chkCnt, info1); std::string sql = "UPDATE " + DBCommon::GetLogTableName(DEVICE_SYNC_TABLE) + " SET extend_field=''"; EXPECT_EQ(ExecuteSQL(sql, info1), E_OK); + sql = "UPDATE " + DBCommon::GetLogTableName(DEVICE_SYNC_TABLE) + " SET extend_field='{}' where data_key > 5"; + EXPECT_EQ(ExecuteSQL(sql, info1), E_OK); EXPECT_EQ(CountTableData(info1, DBCommon::GetLogTableName(DEVICE_SYNC_TABLE), - " json_valid(extend_field) = 0"), 1); + " json_valid(extend_field) = 0 OR json_extract(extend_field, '$') = '{}'"), chkCnt); /** * @tc.steps: step3. Set tracker again and check log. * @tc.expected: step3. Ok */ EXPECT_EQ(SetTrackerTables(info1, {DEVICE_SYNC_TABLE}), E_OK); EXPECT_EQ(CountTableData(info1, DBCommon::GetLogTableName(DEVICE_SYNC_TABLE), - " json_valid(extend_field) = 0"), 0); + " json_valid(extend_field) = 0 OR json_extract(extend_field, '$') = '{}'"), 0); +} + +/** + * @tc.name: UpgradeTracker003 + * @tc.desc: Test extend col names was not set. + * @tc.type: FUNC + * @tc.author: bty + */ +HWTEST_F(DistributedDBRDBUpgradeTest, UpgradeTracker003, TestSize.Level0) +{ + /** + * @tc.steps: step1. Init delegate and set tracker schema. + * @tc.expected: step1. Ok + */ + ASSERT_NO_FATAL_FAILURE(InitUpgradeDelegate()); + auto info1 = GetStoreInfo1(); + EXPECT_EQ(SetTrackerTables(info1, {DEVICE_SYNC_TABLE}), E_OK); + /** + * @tc.steps: step2. Insert local data and not set extend col names. + * @tc.expected: step2. Ok + */ + int chkCnt = 10; + InsertLocalDBData(0, chkCnt, info1); + auto trackerSchema = GetAllTrackerSchema(info1, {DEVICE_SYNC_TABLE}); + auto store = GetDelegate(info1); + ASSERT_NE(store, nullptr); + for (const auto &trackerTable : trackerSchema) { + auto temp = trackerTable; + temp.extendColNames = {}; + EXPECT_EQ(store->SetTrackerTable(temp), E_OK); + } + EXPECT_EQ(CountTableData(info1, DBCommon::GetLogTableName(DEVICE_SYNC_TABLE), + " json_extract(extend_field, '$') = '{}'"), chkCnt); } } \ No newline at end of file