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 f59f7c355d4736e0c70ac37c91df61db08ff8474..c34c59dfb9a63a0292c7fbf974e378de7237aa44 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 @@ -1,3 +1,4 @@ + /* * Copyright (c) 2021 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); @@ -478,6 +479,7 @@ SQLITE_API int sqlite3_open_v2_relational(const char *filename, sqlite3 **ppDb, if (err != SQLITE_OK) { return err; } + printf("open sqlite relational:%p\r\n", *ppDb); PostHandle(*ppDb); return err; } diff --git a/frameworks/libs/distributeddb/storage/src/sqlite/cloud_sync_log_table_manager.cpp b/frameworks/libs/distributeddb/storage/src/sqlite/cloud_sync_log_table_manager.cpp index f54c6ca805c3906a720ddd74e3a3bca607f33a2d..1391e4f33923e7a098e38dcf47134ff73be44819 100644 --- a/frameworks/libs/distributeddb/storage/src/sqlite/cloud_sync_log_table_manager.cpp +++ b/frameworks/libs/distributeddb/storage/src/sqlite/cloud_sync_log_table_manager.cpp @@ -112,7 +112,7 @@ std::string CloudSyncLogTableManager::GetDeleteTrigger(const TableInfo &table, c deleteTrigger += "WHERE key = 'log_trigger_switch' AND VALUE = 'true')\n"; deleteTrigger += "BEGIN\n"; deleteTrigger += "\t UPDATE " + DBConstant::RELATIONAL_PREFIX + table.GetTableName() + "_log"; - deleteTrigger += " SET data_key=-1,flag=0x03,timestamp=get_sys_time(0)"; + deleteTrigger += " SET data_key=-1,flag=0x03,timestamp=get_raw_sys_time()"; deleteTrigger += " WHERE data_key = OLD.rowid;"; deleteTrigger += "END;"; return deleteTrigger; 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 e9cf8dc80bb2f5647041fa60683daf154cf406fe..89656b55b34d455f70e176016cd8886da20d4954 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 @@ -68,6 +68,12 @@ int SQLiteSingleRelationalStorageEngine::RegisterFunction(sqlite3 *db) const if (errCode != E_OK) { LOGE("[engine] register get sys time failed!"); } + + errCode = SQLiteUtils::RegisterGetRawSysTime(db); + if (errCode != E_OK) { + LOGE("[engine] register get raw sys time failed!"); + } + return E_OK; } diff --git a/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_relational_storage_executor.cpp b/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_relational_storage_executor.cpp index 25c2e1c2d3c3b714c9ac774cc6c1f16c46e1231c..e6e38e9bbffe03f1840c657466a50d48958763d1 100644 --- a/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_relational_storage_executor.cpp +++ b/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_relational_storage_executor.cpp @@ -1831,24 +1831,28 @@ int SQLiteSingleVerRelationalStorageExecutor::PutCloudSyncData(const std::string switch (op) { case OpType::INSERT: errCode = InsertCloudData(tableName, vBucket, tableSchema); - if (errCode != errCode) { - break; + if (errCode != E_OK) { + return errCode; } + break; case OpType::UPDATE: errCode = UpdateCloudData(tableName, vBucket, tableSchema); - if (errCode != errCode) { - break; + if (errCode != E_OK) { + return errCode; } + break; case OpType::DELETE: errCode = DeleteCloudData(tableName, vBucket, tableSchema); - if (errCode != errCode) { - break; + if (errCode != E_OK) { + return errCode; } + break; case OpType::ONLY_UPDATE_GID: errCode = UpdateCloudGid(tableName, vBucket, tableSchema); - if (errCode != errCode) { - break; + if (errCode != E_OK) { + return errCode; } + break; case OpType::NOT_HANDLE: default: break; @@ -1881,13 +1885,15 @@ int SQLiteSingleVerRelationalStorageExecutor::InsertCloudData(const std::string } // insert data errCode = SQLiteUtils::StepWithRetry(insertStmt, false); - SQLiteUtils::ResetStatement(insertStmt, true, errCode); if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { errCode = E_OK; } else { - LOGE("insert data failed when save cloud data:%d", errCode); + int ret = E_OK; + SQLiteUtils::ResetStatement(insertStmt, true, ret); + LOGE("insert data failed when save cloud data:%d, reset stmt:%d", errCode, ret); return errCode; } + SQLiteUtils::ResetStatement(insertStmt, true, errCode); // insert log sql = "insert into " + DBConstant::RELATIONAL_PREFIX + tableName + "_log values(?, ?, ?, ?, ?, ?, ?, ?)"; @@ -1908,8 +1914,12 @@ int SQLiteSingleVerRelationalStorageExecutor::InsertCloudData(const std::string if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { errCode = E_OK; } else { - LOGE("insert log data failed when save cloud data:%d", errCode); + int ret = E_OK; + SQLiteUtils::ResetStatement(insertLogStmt, true, ret); + LOGE("insert log data failed when save cloud data:%d, reset stmt:%d", errCode, ret); + return errCode; } + SQLiteUtils::ResetStatement(insertLogStmt, true, errCode); return errCode; } @@ -2104,17 +2114,19 @@ int SQLiteSingleVerRelationalStorageExecutor::UpdateLogRecord(const VBucket &vBu sqlite3_stmt *updateLogStmt = nullptr; std::string logTable = DBConstant::RELATIONAL_PREFIX + tableSchema.name + "_log"; std::string updateLogSql = "update " + logTable + " set "; - std::vector fields; + std::vector updateColName; if (opType == OpType::ONLY_UPDATE_GID) { updateLogSql += "cloud_gid = ?"; - fields.push_back(GetFieldByName(tableSchema, CloudDbConstant::GID_FIELD)); + updateColName.push_back(CloudDbConstant::GID_FIELD); } else { if (opType == OpType::DELETE) { - updateLogSql += "data_key = -1, flag = 1"; + updateLogSql += "data_key = -1, flag = 1, "; + } else { + updateLogSql += "flag = 0, "; } - updateLogSql += ",device = 'cloud', timestamp = ?, cloud_gid = ?"; - fields.push_back(GetFieldByName(tableSchema, CloudDbConstant::MODIFY_FIELD)); - fields.push_back(GetFieldByName(tableSchema, CloudDbConstant::GID_FIELD)); + updateLogSql += "device = 'cloud', timestamp = ?, cloud_gid = ?"; + updateColName.push_back(CloudDbConstant::MODIFY_FIELD); + updateColName.push_back(CloudDbConstant::GID_FIELD); } updateLogSql += " where hash_key = ?"; @@ -2125,7 +2137,7 @@ int SQLiteSingleVerRelationalStorageExecutor::UpdateLogRecord(const VBucket &vBu } std::map pkMap = GetCloudPrimaryKeyFieldMap(tableSchema); - errCode = BindValueToUpdateLogStatement(vBucket, tableSchema, fields, pkMap, updateLogStmt); + errCode = BindValueToUpdateLogStatement(vBucket, tableSchema, updateColName, pkMap, updateLogStmt); if (errCode != E_OK) { LOGE("bind value to update log statement failed when update cloud data, %d", errCode); SQLiteUtils::ResetStatement(updateLogStmt, true, errCode); @@ -2143,12 +2155,26 @@ int SQLiteSingleVerRelationalStorageExecutor::UpdateLogRecord(const VBucket &vBu } int SQLiteSingleVerRelationalStorageExecutor::BindValueToUpdateLogStatement(const VBucket &vBucket, - const TableSchema &tableSchema, const std::vector &fields, std::map &pkMap, + const TableSchema &tableSchema, std::vector &colNames, std::map &pkMap, sqlite3_stmt *updateLogStmt) { - int errCode = BindValueToUpsertStatement(vBucket, fields, updateLogStmt); - if (errCode != E_OK) { - return errCode; + int index = 0; + int errCode = E_OK; + for (const auto &colName : colNames) { + index++; + if (colName == CloudDbConstant::GID_FIELD) { + errCode = SQLiteUtils::BindTextToStatement(updateLogStmt, index, + std::get(vBucket.at(colName))); + } else if (colName == CloudDbConstant::MODIFY_FIELD) { + errCode = SQLiteUtils::BindInt64ToStatement(updateLogStmt, index, std::get(vBucket.at(colName))); + } else { + LOGE("invalid col name when bind value to update log statement."); + return -E_INTERNAL_ERROR; + } + if (errCode != E_OK) { + LOGE("fail to bind value to update log statement."); + return errCode; + } } std::vector hashKey; @@ -2156,7 +2182,7 @@ int SQLiteSingleVerRelationalStorageExecutor::BindValueToUpdateLogStatement(cons if (errCode != E_OK) { return errCode; } - return SQLiteUtils::BindBlobToStatement(updateLogStmt, fields.size() + 1, hashKey); + return SQLiteUtils::BindBlobToStatement(updateLogStmt, index + 1, hashKey); } int SQLiteSingleVerRelationalStorageExecutor::GetDeleteStatementForCloudSync(const TableSchema &tableSchema, diff --git a/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_relational_storage_executor.h b/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_relational_storage_executor.h index 637004d6c149604574c667270fb0356cd08bf0ea..b7eb40786801e4dc09f10dea7e2ef37c84048573 100644 --- a/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_relational_storage_executor.h +++ b/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_relational_storage_executor.h @@ -188,7 +188,7 @@ private: int UpdateLogRecord(const VBucket &vBucket, const TableSchema &tableSchema, OpType opType); int BindValueToUpdateLogStatement(const VBucket &vBucket, const TableSchema &tableSchema, - const std::vector &fields, std::map &pkMap, sqlite3_stmt *updateLogStmt); + std::vector &colNames, std::map &pkMap, sqlite3_stmt *updateLogStmt); int GetDeleteStatementForCloudSync(const TableSchema &tableSchema, const std::set &pkSet, const VBucket &vBucket, sqlite3_stmt *&deleteStmt); diff --git a/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_utils.cpp b/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_utils.cpp index ec0dac0eafc1eda098d82c45fbf2b3a40095c949..8a9ec7590d152f80ad10b49289ced099e4895e10 100644 --- a/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_utils.cpp +++ b/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_utils.cpp @@ -1389,6 +1389,22 @@ void SQLiteUtils::GetSysTime(sqlite3_context *ctx, int argc, sqlite3_value **arg sqlite3_result_int64(ctx, (sqlite3_int64)TimeHelper::GetSysCurrentTime()); } +void SQLiteUtils::GetRawSysTime(sqlite3_context *ctx, int argc, sqlite3_value **argv) +{ + if (ctx == nullptr || argc != 0 || argv == nullptr) { + LOGE("Parameter does not meet restrictions."); + return; + } + + uint64_t curTime = 0; + int errCode = TimeHelper::GetSysCurrentRawTime(curTime); + if (errCode != E_OK) { + sqlite3_result_error(ctx, "get raw sys time failed.", errCode); + return; + } + sqlite3_result_int64(ctx, (sqlite3_int64)(curTime)); +} + void SQLiteUtils::GetLastTime(sqlite3_context *ctx, int argc, sqlite3_value **argv) { if (ctx == nullptr || argc != 0 || argv == nullptr) { @@ -1413,6 +1429,13 @@ int SQLiteUtils::RegisterGetLastTime(sqlite3 *db) return SQLiteUtils::RegisterFunction(db, "get_last_time", 0, nullptr, func); } +int SQLiteUtils::RegisterGetRawSysTime(sqlite3 *db) +{ + TransactFunc func; + func.xFunc = &GetRawSysTime; + return SQLiteUtils::RegisterFunction(db, "get_raw_sys_time", 0, nullptr, func); +} + int SQLiteUtils::CreateSameStuTable(sqlite3 *db, const TableInfo &baseTbl, const std::string &newTableName) { std::string sql = "CREATE TABLE IF NOT EXISTS '" + newTableName + "' ("; diff --git a/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_utils.h b/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_utils.h index 259b9ebb7e62b68fb937ad289516a3aaf34799df..8d747d9fbe3b0460556412e99583fcb8e5b6125a 100644 --- a/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_utils.h +++ b/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_utils.h @@ -168,6 +168,8 @@ public: static int RegisterGetLastTime(sqlite3 *db); + static int RegisterGetRawSysTime(sqlite3 *db); + static int CreateRelationalLogTable(sqlite3 *db, const std::string &oriTableName); static int AddRelationalLogTableTrigger(sqlite3 *db, const std::string &identity, const TableInfo &table); @@ -228,6 +230,7 @@ private: static void GetSysTime(sqlite3_context *ctx, int argc, sqlite3_value **argv); static void GetLastTime(sqlite3_context *ctx, int argc, sqlite3_value **argv); + static void GetRawSysTime(sqlite3_context *ctx, int argc, sqlite3_value **argv); static int SetDataBaseProperty(sqlite3 *db, const OpenDbProperties &properties, bool setWal, const std::vector &sqls); diff --git a/frameworks/libs/distributeddb/syncer/src/time_helper.cpp b/frameworks/libs/distributeddb/syncer/src/time_helper.cpp index c4d3c21729d6ee2380206bfb018d646ca07f394a..7f395bcbbed921680a55b57a485498a7d1c7887e 100644 --- a/frameworks/libs/distributeddb/syncer/src/time_helper.cpp +++ b/frameworks/libs/distributeddb/syncer/src/time_helper.cpp @@ -47,6 +47,16 @@ Timestamp TimeHelper::GetSysCurrentTime() return (curTime * TO_100_NS) + currentIncCount_; // Currently Timestamp is uint64_t } +int TimeHelper::GetSysCurrentRawTime(uint64_t &curTime) +{ + int errCode = OS::GetCurrentSysTimeInMicrosecond(curTime); + if (errCode != 0) { + return errCode; + } + curTime *= TO_100_NS; + return E_OK; +} + TimeHelper::TimeHelper() : storage_(nullptr), metadata_(nullptr) diff --git a/frameworks/libs/distributeddb/syncer/src/time_helper.h b/frameworks/libs/distributeddb/syncer/src/time_helper.h index 62e5a362c5a53faed54f200ae91005f7e95ceb7b..80a86765dba315498451743fca7b7ff9c49a56bd 100644 --- a/frameworks/libs/distributeddb/syncer/src/time_helper.h +++ b/frameworks/libs/distributeddb/syncer/src/time_helper.h @@ -39,6 +39,7 @@ public: // Get current system time static Timestamp GetSysCurrentTime(); + static int GetSysCurrentRawTime(uint64_t &currTime); TimeHelper(); ~TimeHelper(); diff --git a/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_save_cloud_data_test.cpp b/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_save_cloud_data_test.cpp index 80fc6a5fe134c39fac2114890c6237b8d7440db6..9ae4917f9650ea80fb21a87f656319107dddfbd8 100644 --- a/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_save_cloud_data_test.cpp +++ b/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_save_cloud_data_test.cpp @@ -85,7 +85,6 @@ namespace { } EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); - /** * @tc.steps:step2. create distributed table with CLOUD_COOPERATION mode. * @tc.expected: step2. return ok. @@ -96,7 +95,8 @@ namespace { * @tc.steps:step3. insert one row. * @tc.expected: step3. return ok. */ - sql = "insert into " + tableName + " values(1, 'ab');"; + sql = "insert into " + tableName + + " values(1, 'zhangsan1'), (2, 'zhangsan2'), (3, 'zhangsan3'), (4, 'zhangsan4');"; EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); EXPECT_EQ(sqlite3_close_v2(db), E_OK); } @@ -152,6 +152,9 @@ namespace { void DistributedDBSaveCloudDataTest::TearDown() { + RefObject::DecObjRef(g_store); + EXPECT_EQ(g_mgr.CloseStore(g_delegate), OK); + g_delegate = nullptr; DistributedDBToolsUnitTest::RemoveTestDbFiles(g_testDir); } @@ -176,14 +179,14 @@ namespace { PrepareDataBase(g_tableName, true); /** - * @tc.steps:step2. call GetLogInfoByPrimaryKeyOrGid with id = 2. + * @tc.steps:step2. call GetLogInfoByPrimaryKeyOrGid with id = 100. * @tc.expected: step2. return E_NOT_FOUND. */ std::shared_ptr storageProxy = GetStorageProxy(g_cloudStore); ASSERT_NE(storageProxy, nullptr); EXPECT_EQ(storageProxy->StartTransaction(), E_OK); VBucket vBucket; - vBucket["id"] = 2L ; + vBucket["id"] = 100L ; std::string gid = ""; vBucket["GID_FIELD"] = gid; LogInfo logInfo; @@ -196,4 +199,57 @@ namespace { vBucket["id"] = 1L; EXPECT_EQ(storageProxy->GetLogInfoByPrimaryKeyOrGid(g_tableName, vBucket, logInfo), E_OK); } + + void ConstructDownloadData(DownloadData &downloadData) + { + for (int i = 0; i < 4; i++) { + VBucket vBucket; + if (i == 3) { + vBucket["id"] = 2L + i; // id = 4 already pre_insert + } else { + vBucket["id"] = 1L + i; + } + + std::string name = "lisi" + std::to_string(i); + vBucket["name"] = name; + std::string gid = "abcd" + std::to_string(i); + vBucket[CloudDbConstant::GID_FIELD] = gid; + int64_t cTime = 12345678L + i; + vBucket[CloudDbConstant::CREATE_FIELD] = cTime; + int64_t mTime = 12345679L + i; + vBucket[CloudDbConstant::MODIFY_FIELD] = mTime; + downloadData.data.push_back(vBucket); + } + + downloadData.opType = { OpType::UPDATE, OpType::DELETE, OpType::ONLY_UPDATE_GID, OpType::INSERT }; + } + + /** + * @tc.name: PutCloudSyncDataTest001 + * @tc.desc: Test get_raw_sys_time has been registered in sqlite + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangshijie + */ + HWTEST_F(DistributedDBSaveCloudDataTest, PutCloudSyncDataTest001, TestSize.Level0) + { + /** + * @tc.steps:step1. create db, create table. + * @tc.expected: step1. return ok. + */ + PrepareDataBase(g_tableName, true); + + /** + * @tc.steps:step2. call PutCloudSyncData + * @tc.expected: step2. return ok. + */ + std::shared_ptr storageProxy = GetStorageProxy(g_cloudStore); + ASSERT_NE(storageProxy, nullptr); + EXPECT_EQ(storageProxy->StartTransaction(TransactType::IMMEDIATE), E_OK); + + DownloadData downloadData; + ConstructDownloadData(downloadData); + EXPECT_EQ(storageProxy->PutCloudSyncData(g_tableName, downloadData), E_OK); + EXPECT_EQ(storageProxy->Commit(), E_OK); + } }