1 /*
2  * Copyright (c) 2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #ifdef RELATIONAL_STORE
16 #include <gtest/gtest.h>
17 #include "cloud/cloud_storage_utils.h"
18 #include "cloud/cloud_db_constant.h"
19 #include "cloud/cloud_db_types.h"
20 #include "db_common.h"
21 #include "distributeddb_data_generate_unit_test.h"
22 #include "log_print.h"
23 #include "relational_store_delegate.h"
24 #include "relational_store_manager.h"
25 #include "runtime_config.h"
26 #include "sqlite_relational_utils.h"
27 #include "time_helper.h"
28 #include "virtual_asset_loader.h"
29 #include "virtual_cloud_data_translate.h"
30 #include "virtual_cloud_db.h"
31 #include "virtual_communicator_aggregator.h"
32 
33 namespace {
34 using namespace testing::ext;
35 using namespace DistributedDB;
36 using namespace DistributedDBUnitTest;
37 class DistributedDBCloudReferenceSyncTest : public testing::Test {
38 public:
39     static void SetUpTestCase();
40     static void TearDownTestCase();
41     void SetUp() override;
42     void TearDown() override;
43 protected:
44     void InitTestDir();
45     DataBaseSchema GetSchema();
46     void CloseDb();
47     void SetReference();
48     void InsertUserTableRecord(const std::string &tableName, int64_t recordCounts, bool isShared = false,
49         int64_t begin = 0, std::string owner = "");
50     void UpdateUserTableRecord(const std::string &tableName, int64_t begin, int64_t count);
51     void DeleteUserTableRecord(const std::string &tableName, int64_t begin, int64_t count);
52     void InsertCloudSharedTableRecord(int64_t begin, int64_t count, int64_t photoSize, bool assetIsNull);
53     void UpdateCloudSharedTableRecord(int64_t begin, int64_t count, int64_t photoSize, bool assetIsNull);
54     void DeleteCloudSharedTableRecordByGid(int64_t begin, int64_t count);
55     void CheckCloudData(const std::string &tableName, bool hasRef, const std::vector<Entries> &refData);
56     void CheckDistributedSharedData(const std::vector<std::string> &expect);
57     void CheckSharedDataAfterUpdated(const std::vector<double> &expect);
58     DataBaseSchema GetSchema(const std::vector<std::string> &tableNames);
59     std::vector<std::string> InitMultiTable(int count);
60     static void InitWalModeAndTable(sqlite3 *db, const std::vector<std::string> &tableName);
61     std::string testDir_;
62     std::string storePath_;
63     sqlite3 *db_ = nullptr;
64     RelationalStoreDelegate *delegate_ = nullptr;
65     std::shared_ptr<VirtualCloudDb> virtualCloudDb_ = nullptr;
66     VirtualCommunicatorAggregator *communicatorAggregator_ = nullptr;
67     std::shared_ptr<RelationalStoreManager> mgr_ = nullptr;
68     const std::string parentTableName_ = "parent";
69     const std::string sharedParentTableName_ = "parent_shared";
70     const std::string childTableName_ = "child";
71     const std::string sharedChildTableName_ = "child_shared";
72     const std::vector<std::string> sharedTables_ = { sharedParentTableName_, sharedChildTableName_ };
73     const Asset cloudAsset1_ = {
74         .version = 2, .name = "Phone", .assetId = "0", .subpath = "/local/sync", .uri = "/cloud/sync",
75         .modifyTime = "123456", .createTime = "0", .size = "1024", .hash = "DEC"
76     };
77     const Asset cloudAsset2_ = {
78         .version = 2, .name = "Phone", .assetId = "0", .subpath = "/local/sync", .uri = "/cloud/sync",
79         .modifyTime = "123456", .createTime = "0", .size = "1024", .hash = "UPDATE"
80     };
81 };
82 
SetUpTestCase()83 void DistributedDBCloudReferenceSyncTest::SetUpTestCase()
84 {
85     RuntimeConfig::SetCloudTranslate(std::make_shared<VirtualCloudDataTranslate>());
86 }
87 
TearDownTestCase()88 void DistributedDBCloudReferenceSyncTest::TearDownTestCase()
89 {}
90 
SetUp()91 void DistributedDBCloudReferenceSyncTest::SetUp()
92 {
93     DistributedDBToolsUnitTest::PrintTestCaseInfo();
94     InitTestDir();
95     if (DistributedDBToolsUnitTest::RemoveTestDbFiles(testDir_) != 0) {
96         LOGE("rm test db files error.");
97     }
98     DistributedDBToolsUnitTest::PrintTestCaseInfo();
99     LOGD("Test dir is %s", testDir_.c_str());
100     db_ = RelationalTestUtils::CreateDataBase(storePath_);
101     ASSERT_NE(db_, nullptr);
102     InitWalModeAndTable(db_, { parentTableName_, childTableName_ });
103     mgr_ = std::make_shared<RelationalStoreManager>(APP_ID, USER_ID);
104     RelationalStoreDelegate::Option option;
105     ASSERT_EQ(mgr_->OpenStore(storePath_, STORE_ID_1, option, delegate_), DBStatus::OK);
106     ASSERT_NE(delegate_, nullptr);
107     virtualCloudDb_ = std::make_shared<VirtualCloudDb>();
108     ASSERT_EQ(delegate_->SetCloudDB(virtualCloudDb_), DBStatus::OK);
109     ASSERT_EQ(delegate_->SetIAssetLoader(std::make_shared<VirtualAssetLoader>()), DBStatus::OK);
110     ASSERT_EQ(delegate_->CreateDistributedTable(parentTableName_, CLOUD_COOPERATION), DBStatus::OK);
111     ASSERT_EQ(delegate_->CreateDistributedTable(childTableName_, CLOUD_COOPERATION), DBStatus::OK);
112     SetReference();
113     DataBaseSchema dataBaseSchema = GetSchema();
114     ASSERT_EQ(delegate_->SetCloudDbSchema(dataBaseSchema), DBStatus::OK);
115     communicatorAggregator_ = new (std::nothrow) VirtualCommunicatorAggregator();
116     ASSERT_TRUE(communicatorAggregator_ != nullptr);
117     RuntimeContext::GetInstance()->SetCommunicatorAggregator(communicatorAggregator_);
118 }
119 
TearDown()120 void DistributedDBCloudReferenceSyncTest::TearDown()
121 {
122     virtualCloudDb_->ForkQuery(nullptr);
123     CloseDb();
124     EXPECT_EQ(sqlite3_close_v2(db_), SQLITE_OK);
125     if (DistributedDBToolsUnitTest::RemoveTestDbFiles(testDir_) != E_OK) {
126         LOGE("rm test db files error.");
127     }
128     RuntimeContext::GetInstance()->SetCommunicatorAggregator(nullptr);
129     communicatorAggregator_ = nullptr;
130     RuntimeContext::GetInstance()->SetProcessSystemApiAdapter(nullptr);
131 }
132 
InitTestDir()133 void DistributedDBCloudReferenceSyncTest::InitTestDir()
134 {
135     if (!testDir_.empty()) {
136         return;
137     }
138     DistributedDBToolsUnitTest::TestDirInit(testDir_);
139     storePath_ = testDir_ + "/" + STORE_ID_1 + ".db";
140     LOGI("The test db is:%s", testDir_.c_str());
141 }
142 
GetSchema()143 DataBaseSchema DistributedDBCloudReferenceSyncTest::GetSchema()
144 {
145     DataBaseSchema schema;
146     TableSchema tableSchema;
147     tableSchema.name = parentTableName_;
148     tableSchema.sharedTableName = sharedParentTableName_;
149     tableSchema.fields = {
150         {"id", TYPE_INDEX<std::string>, true}, {"name", TYPE_INDEX<std::string>}, {"height", TYPE_INDEX<double>},
151         {"photo", TYPE_INDEX<Bytes>}, {"age", TYPE_INDEX<int64_t>}
152     };
153     TableSchema childSchema;
154     childSchema.name = childTableName_;
155     childSchema.sharedTableName = sharedChildTableName_;
156     childSchema.fields = {
157         {"id", TYPE_INDEX<std::string>, true}, {"name", TYPE_INDEX<std::string>}, {"height", TYPE_INDEX<double>},
158         {"photo", TYPE_INDEX<Bytes>}, {"age", TYPE_INDEX<int64_t>}
159     };
160     schema.tables.push_back(tableSchema);
161     schema.tables.push_back(childSchema);
162     return schema;
163 }
164 
GetSchema(const std::vector<std::string> & tableNames)165 DataBaseSchema DistributedDBCloudReferenceSyncTest::GetSchema(const std::vector<std::string> &tableNames)
166 {
167     DataBaseSchema schema;
168     for (const auto &table : tableNames) {
169         TableSchema tableSchema;
170         tableSchema.name = table;
171         tableSchema.sharedTableName = table + "_shared";
172         tableSchema.fields = {
173             {"id", TYPE_INDEX<std::string>, true}, {"name", TYPE_INDEX<std::string>}, {"height", TYPE_INDEX<double>},
174             {"photo", TYPE_INDEX<Bytes>}, {"age", TYPE_INDEX<int64_t>}
175         };
176         schema.tables.push_back(tableSchema);
177     }
178     return schema;
179 }
180 
CloseDb()181 void DistributedDBCloudReferenceSyncTest::CloseDb()
182 {
183     virtualCloudDb_ = nullptr;
184     EXPECT_EQ(mgr_->CloseStore(delegate_), DBStatus::OK);
185     delegate_ = nullptr;
186     mgr_ = nullptr;
187 }
188 
SetReference()189 void DistributedDBCloudReferenceSyncTest::SetReference()
190 {
191     std::vector<TableReferenceProperty> tableReferenceProperty;
192     TableReferenceProperty property;
193     property.sourceTableName = childTableName_;
194     property.targetTableName = parentTableName_;
195     property.columns["name"] = "name";
196     tableReferenceProperty.push_back(property);
197     delegate_->SetReference(tableReferenceProperty);
198 }
199 
InitWalModeAndTable(sqlite3 * db,const std::vector<std::string> & tableName)200 void DistributedDBCloudReferenceSyncTest::InitWalModeAndTable(sqlite3 *db, const std::vector<std::string> &tableName)
201 {
202     ASSERT_NE(db, nullptr);
203     EXPECT_EQ(RelationalTestUtils::ExecSql(db, "PRAGMA journal_mode=WAL;"), SQLITE_OK);
204     static constexpr const char *createSQLBegin =  "CREATE TABLE IF NOT EXISTS ";
205     static constexpr const char *createSQLEnd =  " (" \
206         "id TEXT PRIMARY KEY," \
207         "name TEXT," \
208         "height REAL ," \
209         "photo BLOB," \
210         "age INT);";
211     for (const auto &table : tableName) {
212         std::string createSQL = createSQLBegin + table + createSQLEnd;
213         LOGD("[DistributedDBCloudReferenceSyncTest] create sql is %s", createSQL.c_str());
214         EXPECT_EQ(RelationalTestUtils::ExecSql(db, createSQL), SQLITE_OK);
215     }
216 }
217 
InsertUserTableRecord(const std::string & tableName,int64_t recordCounts,bool isShared,int64_t begin,std::string owner)218 void DistributedDBCloudReferenceSyncTest::InsertUserTableRecord(const std::string &tableName,
219     int64_t recordCounts, bool isShared, int64_t begin, std::string owner)
220 {
221     ASSERT_NE(db_, nullptr);
222     for (int64_t i = begin; i < recordCounts; ++i) {
223         string sql = "INSERT OR REPLACE INTO " + tableName + " (";
224         if (isShared) {
225             sql += " cloud_owner, cloud_privilege,";
226         }
227         sql += " id, name, height, photo, age) VALUES (";
228         if (isShared) {
229             if (owner.empty()) {
230                 sql += "'mock_owner', 'true', ";
231             } else {
232                 sql += "'" + owner + "', 'true', ";
233             }
234         }
235         sql += "'" + std::to_string(i) + "', 'Local";
236         sql += std::to_string(i) + "', '155.10',  'text', '21');";
237         ASSERT_EQ(SQLiteUtils::ExecuteRawSQL(db_, sql), E_OK);
238     }
239 }
240 
UpdateUserTableRecord(const std::string & tableName,int64_t begin,int64_t count)241 void DistributedDBCloudReferenceSyncTest::UpdateUserTableRecord(const std::string &tableName, int64_t begin,
242     int64_t count)
243 {
244     string updateAge = "UPDATE " + tableName + " SET age = '99' where id in (";
245     for (int64_t j = begin; j < begin + count; ++j) {
246         updateAge += "'" + std::to_string(j) + "',";
247     }
248     updateAge.pop_back();
249     updateAge += ");";
250     ASSERT_EQ(RelationalTestUtils::ExecSql(db_, updateAge), SQLITE_OK);
251 }
252 
DeleteUserTableRecord(const std::string & tableName,int64_t begin,int64_t count)253 void DistributedDBCloudReferenceSyncTest::DeleteUserTableRecord(const std::string &tableName, int64_t begin,
254     int64_t count)
255 {
256     for (int64_t i = begin; i < begin + count; i++) {
257         string sql = "Delete from " + tableName + " where id = " + std::to_string(i) + ";";
258         ASSERT_EQ(RelationalTestUtils::ExecSql(db_, sql), SQLITE_OK);
259     }
260 }
261 
InsertCloudSharedTableRecord(int64_t begin,int64_t count,int64_t photoSize,bool assetIsNull)262 void DistributedDBCloudReferenceSyncTest::InsertCloudSharedTableRecord(int64_t begin, int64_t count, int64_t photoSize,
263     bool assetIsNull)
264 {
265     std::vector<uint8_t> photo(photoSize, 'v');
266     std::vector<VBucket> record1;
267     std::vector<VBucket> record2;
268     std::vector<VBucket> extend1;
269     std::vector<VBucket> extend2;
270     Timestamp now = TimeHelper::GetSysCurrentTime();
271     for (int64_t i = begin; i < begin + count; ++i) {
272         VBucket data;
273         data.insert_or_assign(std::string("id"), std::to_string(i));
274         data.insert_or_assign(std::string("name"), std::string("Cloud") + std::to_string(i));
275         data.insert_or_assign(std::string("height"), 166.0); // 166.0 is random double value
276         data.insert_or_assign(std::string("photo"), photo);
277         data.insert_or_assign(std::string("age"), 13L); // 13 is random int64_t value
278         data.insert_or_assign(std::string("cloud_owner"), std::string("a_owner"));
279         data.insert_or_assign(std::string("cloud_privilege"), std::string("true"));
280         Asset asset = cloudAsset1_;
281         asset.name = asset.name + std::to_string(i);
282         assetIsNull ? data.insert_or_assign(std::string("asset"), Nil()) :
283             data.insert_or_assign(std::string("asset"), asset);
284         record1.push_back(data);
285         record2.push_back(data);
286         VBucket log;
287         log.insert_or_assign(CloudDbConstant::CREATE_FIELD,
288             static_cast<int64_t>(now / CloudDbConstant::TEN_THOUSAND + i));
289         log.insert_or_assign(CloudDbConstant::MODIFY_FIELD,
290             static_cast<int64_t>(now / CloudDbConstant::TEN_THOUSAND + i));
291         log.insert_or_assign(CloudDbConstant::DELETE_FIELD, false);
292         extend1.push_back(log);
293         extend2.push_back(log);
294     }
295     ASSERT_EQ(virtualCloudDb_->BatchInsert(sharedParentTableName_, std::move(record1), extend1), DBStatus::OK);
296     ASSERT_EQ(virtualCloudDb_->BatchInsert(sharedChildTableName_, std::move(record2), extend2), DBStatus::OK);
297     std::this_thread::sleep_for(std::chrono::milliseconds(count));
298 }
299 
UpdateCloudSharedTableRecord(int64_t begin,int64_t count,int64_t photoSize,bool assetIsNull)300 void DistributedDBCloudReferenceSyncTest::UpdateCloudSharedTableRecord(int64_t begin, int64_t count, int64_t photoSize,
301     bool assetIsNull)
302 {
303     std::vector<uint8_t> photo(photoSize, 'v');
304     std::vector<VBucket> record1;
305     std::vector<VBucket> record2;
306     std::vector<VBucket> extend1;
307     std::vector<VBucket> extend2;
308     Timestamp now = TimeHelper::GetSysCurrentTime();
309     for (int64_t i = begin; i < begin + 2 * count; ++i) { // 2 is two tables shared only one gid
310         VBucket data;
311         data.insert_or_assign("id", std::to_string(i));
312         data.insert_or_assign("name", std::string("Cloud") + std::to_string(i));
313         data.insert_or_assign("height", 188.0); // 188.0 is random double value
314         data.insert_or_assign("photo", photo);
315         data.insert_or_assign("age", 13L); // 13 is random int64_t value
316         data.insert_or_assign("cloud_owner", std::string("b_owner"));
317         data.insert_or_assign("cloud_privilege", std::string("true"));
318         Asset asset = cloudAsset2_;
319         asset.name = asset.name + std::to_string(i);
320         assetIsNull ? data.insert_or_assign("asset", Nil()) : data.insert_or_assign("asset", asset);
321         record1.push_back(data);
322         record2.push_back(data);
323         VBucket log;
324         log.insert_or_assign(CloudDbConstant::CREATE_FIELD,
325             static_cast<int64_t>(now / CloudDbConstant::TEN_THOUSAND + i));
326         log.insert_or_assign(CloudDbConstant::MODIFY_FIELD,
327             static_cast<int64_t>(now / CloudDbConstant::TEN_THOUSAND + i));
328         log.insert_or_assign(CloudDbConstant::DELETE_FIELD, false);
329         log.insert_or_assign(CloudDbConstant::GID_FIELD, std::to_string(i));
330         extend1.push_back(log);
331         log.insert_or_assign(CloudDbConstant::GID_FIELD, std::to_string(++i));
332         extend2.push_back(log);
333     }
334     ASSERT_EQ(virtualCloudDb_->BatchUpdate(sharedParentTableName_, std::move(record1), extend1), DBStatus::OK);
335     ASSERT_EQ(virtualCloudDb_->BatchUpdate(sharedChildTableName_, std::move(record2), extend2), DBStatus::OK);
336     std::this_thread::sleep_for(std::chrono::milliseconds(count));
337 }
338 
DeleteCloudSharedTableRecordByGid(int64_t begin,int64_t count)339 void DistributedDBCloudReferenceSyncTest::DeleteCloudSharedTableRecordByGid(int64_t begin, int64_t count)
340 {
341     for (size_t i = 0; i < sharedTables_.size(); i++) {
342         for (int64_t j = begin; j < begin + count; ++j) {
343             VBucket data;
344             data.insert_or_assign(CloudDbConstant::GID_FIELD, std::to_string(j));
345             ASSERT_EQ(virtualCloudDb_->DeleteByGid(sharedTables_[i], data), DBStatus::OK);
346         }
347     }
348     std::this_thread::sleep_for(std::chrono::milliseconds(count));
349 }
350 
CheckCloudData(const std::string & tableName,bool hasRef,const std::vector<Entries> & refData)351 void DistributedDBCloudReferenceSyncTest::CheckCloudData(const std::string &tableName, bool hasRef,
352     const std::vector<Entries> &refData)
353 {
354     VBucket extend;
355     extend[CloudDbConstant::CURSOR_FIELD] = std::string();
356     std::vector<VBucket> queryRes;
357     (void) virtualCloudDb_->Query(tableName, extend, queryRes);
358     if (hasRef) {
359         ASSERT_EQ(refData.size(), queryRes.size());
360     }
361     int index = 0;
362     for (const auto &data : queryRes) {
363         if (!hasRef) {
364             EXPECT_EQ(data.find(CloudDbConstant::REFERENCE_FIELD), data.end());
365             continue;
366         }
367         ASSERT_NE(data.find(CloudDbConstant::REFERENCE_FIELD), data.end());
368         Entries entries = std::get<Entries>(data.at(CloudDbConstant::REFERENCE_FIELD));
369         EXPECT_EQ(refData[index], entries);
370         index++;
371     }
372 }
373 
CheckDistributedSharedData(const std::vector<std::string> & expect)374 void DistributedDBCloudReferenceSyncTest::CheckDistributedSharedData(const std::vector<std::string> &expect)
375 {
376     for (size_t i = 0; i < sharedTables_.size(); i++) {
377         std::string sql = "SELECT version FROM " + DBCommon::GetLogTableName(sharedTables_[i]) + " WHERE rowid = 1;";
378         sqlite3_stmt *stmt = nullptr;
379         ASSERT_EQ(SQLiteUtils::GetStatement(db_, sql, stmt), E_OK);
380         while (SQLiteUtils::StepWithRetry(stmt) == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) {
381             ASSERT_EQ(sqlite3_column_type(stmt, 0), SQLITE_TEXT);
382             Type cloudValue;
383             ASSERT_EQ(SQLiteRelationalUtils::GetCloudValueByType(stmt, TYPE_INDEX<std::string>, 0, cloudValue), E_OK);
384             std::string versionValue;
385             ASSERT_EQ(CloudStorageUtils::GetValueFromOneField(cloudValue, versionValue), E_OK);
386             ASSERT_EQ(versionValue, expect[i]);
387         }
388         int errCode;
389         SQLiteUtils::ResetStatement(stmt, true, errCode);
390     }
391 }
392 
CheckSharedDataAfterUpdated(const std::vector<double> & expect)393 void DistributedDBCloudReferenceSyncTest::CheckSharedDataAfterUpdated(const std::vector<double> &expect)
394 {
395     for (size_t i = 0; i < sharedTables_.size(); i++) {
396         std::string sql = "SELECT height FROM " + sharedTables_[i] + " WHERE _rowid_ = 1;";
397         sqlite3_stmt *stmt = nullptr;
398         ASSERT_EQ(SQLiteUtils::GetStatement(db_, sql, stmt), E_OK);
399         while (SQLiteUtils::StepWithRetry(stmt) == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) {
400             ASSERT_EQ(sqlite3_column_type(stmt, 0), SQLITE_FLOAT);
401             Type cloudValue;
402             ASSERT_EQ(SQLiteRelationalUtils::GetCloudValueByType(stmt, TYPE_INDEX<double>, 0, cloudValue), E_OK);
403             double heightValue;
404             ASSERT_EQ(CloudStorageUtils::GetValueFromOneField(cloudValue, heightValue), E_OK);
405             EXPECT_EQ(heightValue, expect[i]);
406         }
407         int errCode;
408         SQLiteUtils::ResetStatement(stmt, true, errCode);
409     }
410 }
411 
InitMultiTable(int count)412 std::vector<std::string> DistributedDBCloudReferenceSyncTest::InitMultiTable(int count)
413 {
414     std::vector<std::string> tableName;
415     for (int i = 0; i < count; ++i) {
416         std::string table = "table_";
417         table += static_cast<char>(static_cast<int>('a') + i);
418         tableName.push_back(table);
419     }
420     InitWalModeAndTable(db_, tableName);
421     for (const auto &table : tableName) {
422         EXPECT_EQ(delegate_->CreateDistributedTable(table, CLOUD_COOPERATION), DBStatus::OK);
423         LOGW("table %s", table.c_str());
424     }
425     return tableName;
426 }
427 
428 /**
429  * @tc.name: CloudSyncTest001
430  * @tc.desc: sync table with reference
431  * @tc.type: FUNC
432  * @tc.require:
433  * @tc.author: zhangqiquan
434  */
435 HWTEST_F(DistributedDBCloudReferenceSyncTest, CloudSyncTest001, TestSize.Level0)
436 {
437     std::vector<std::string> tableNames = { parentTableName_, childTableName_ };
438     Query query = Query::Select().FromTable(tableNames);
439     RelationalTestUtils::CloudBlockSync(query, delegate_);
440 
441     InsertUserTableRecord(parentTableName_, 1);
442     InsertUserTableRecord(childTableName_, 1);
443     RelationalTestUtils::CloudBlockSync(query, delegate_);
444     LOGD("check parent table");
445     CheckCloudData(parentTableName_, false, {});
446     LOGD("check child table");
447     std::vector<Entries> expectEntries;
448     Entries entries;
449     entries[parentTableName_] = "0";
450     expectEntries.push_back(entries);
451     CheckCloudData(childTableName_, true, expectEntries);
452 }
453 
454 /**
455  * @tc.name: CloudSyncTest002
456  * @tc.desc: sync shared table with reference
457  * @tc.type: FUNC
458  * @tc.require:
459  * @tc.author: zhangqiquan
460  */
461 HWTEST_F(DistributedDBCloudReferenceSyncTest, CloudSyncTest002, TestSize.Level0)
462 {
463     std::vector<std::string> tableNames = { sharedParentTableName_, sharedChildTableName_ };
464     Query query = Query::Select().FromTable(tableNames);
465     RelationalTestUtils::CloudBlockSync(query, delegate_);
466 
467     InsertUserTableRecord(sharedParentTableName_, 1, true);
468     InsertUserTableRecord(sharedChildTableName_, 1, true);
469     RelationalTestUtils::CloudBlockSync(query, delegate_);
470     LOGD("check parent table");
471     CheckCloudData(sharedParentTableName_, false, {});
472     LOGD("check child table");
473     std::vector<Entries> expectEntries;
474     Entries entries;
475     entries[sharedParentTableName_] = "0";
476     expectEntries.push_back(entries);
477     CheckCloudData(sharedChildTableName_, true, expectEntries);
478 }
479 
480 /**
481  * @tc.name: CloudSyncTest003
482  * @tc.desc: sync with invalid table reference
483  * @tc.type: FUNC
484  * @tc.require:
485  * @tc.author: zhangqiquan
486  */
487 HWTEST_F(DistributedDBCloudReferenceSyncTest, CloudSyncTest003, TestSize.Level0)
488 {
489     std::vector<std::string> tableNames = { childTableName_, parentTableName_ };
490     Query query = Query::Select().FromTable(tableNames);
491     RelationalTestUtils::CloudBlockSync(query, delegate_, DistributedDB::INVALID_ARGS);
492 
493     tableNames = { sharedChildTableName_, sharedParentTableName_ };
494     query = Query::Select().FromTable(tableNames);
495     RelationalTestUtils::CloudBlockSync(query, delegate_, DistributedDB::INVALID_ARGS);
496 
497     tableNames = { sharedChildTableName_, parentTableName_ };
498     query = Query::Select().FromTable(tableNames);
499     RelationalTestUtils::CloudBlockSync(query, delegate_, DistributedDB::OK);
500 
501     tableNames = { childTableName_, sharedParentTableName_ };
502     query = Query::Select().FromTable(tableNames);
503     RelationalTestUtils::CloudBlockSync(query, delegate_, DistributedDB::OK);
504 }
505 
506 /**
507  * @tc.name: CloudSyncTest004
508  * @tc.desc: sync shared table and check version, cloud insert, local update, local delete
509  * @tc.type: FUNC
510  * @tc.require:
511  * @tc.author: chenchaohao
512  */
513 HWTEST_F(DistributedDBCloudReferenceSyncTest, CloudSyncTest004, TestSize.Level0)
514 {
515     /**
516      * @tc.steps: step1. cloud insert records then sync, check distributed shared table
517      * @tc.expected: OK.
518      */
519     int64_t num = 200;
520     std::vector<std::string> tableNames = { sharedParentTableName_, sharedChildTableName_ };
521     Query query = Query::Select().FromTable(tableNames);
522     RelationalTestUtils::CloudBlockSync(query, delegate_);
523     InsertCloudSharedTableRecord(0, num, 10240, true);
524     RelationalTestUtils::CloudBlockSync(query, delegate_);
525     CheckDistributedSharedData({"0", "200"});
526 
527     /**
528      * @tc.steps: step2. user update records then sync, check distributed shared table
529      * @tc.expected: OK.
530      */
531     UpdateUserTableRecord(sharedParentTableName_, 0, num);
532     UpdateUserTableRecord(sharedChildTableName_, 0, num);
533     RelationalTestUtils::CloudBlockSync(query, delegate_);
534     CheckDistributedSharedData({"400", "600"});
535     CheckCloudData(sharedParentTableName_, false, {});
536     std::vector<Entries> expectEntries;
537     Entries entries;
538     for (size_t i = 0; i < 100; i++) { // 100 is max cloud query num
539         entries[sharedParentTableName_] = std::to_string(i);
540         expectEntries.push_back(entries);
541     }
542     CheckCloudData(sharedChildTableName_, true, expectEntries);
543 
544     /**
545      * @tc.steps: step3. user delete records then sync, check distributed shared table
546      * @tc.expected: OK.
547      */
548     DeleteUserTableRecord(sharedParentTableName_, 0, 1);
549     DeleteUserTableRecord(sharedChildTableName_, 0, 1);
550     RelationalTestUtils::CloudBlockSync(query, delegate_);
551     CheckDistributedSharedData({"400", "600"});
552 }
553 
554 /**
555  * @tc.name: CloudSyncTest005
556  * @tc.desc: sync shared table and check version, local insert, cloud delete, local update
557  * @tc.type: FUNC
558  * @tc.require:
559  * @tc.author: chenchaohao
560  */
561 HWTEST_F(DistributedDBCloudReferenceSyncTest, CloudSyncTest005, TestSize.Level0)
562 {
563     /**
564      * @tc.steps: step1. user insert records then sync, check distributed shared table
565      * @tc.expected: OK.
566      */
567     std::vector<std::string> tableNames = { sharedParentTableName_, sharedChildTableName_ };
568     Query query = Query::Select().FromTable(tableNames);
569     RelationalTestUtils::CloudBlockSync(query, delegate_);
570     InsertUserTableRecord(sharedParentTableName_, 1, true, 0);
571     InsertUserTableRecord(sharedChildTableName_, 1, true, 0);
572     RelationalTestUtils::CloudBlockSync(query, delegate_);
573     CheckDistributedSharedData({"0", "1"});
574 
575     /**
576      * @tc.steps: step2. user update records then sync, check distributed shared table
577      * @tc.expected: OK.
578      */
579     DeleteCloudSharedTableRecordByGid(0, 2);
580     UpdateUserTableRecord(sharedParentTableName_, 0, 1);
581     UpdateUserTableRecord(sharedChildTableName_, 0, 1);
582     RelationalTestUtils::CloudBlockSync(query, delegate_);
583     CheckDistributedSharedData({"2", "3"});
584     CheckCloudData(sharedParentTableName_, false, {});
585     std::vector<Entries> expectEntries;
586     Entries entries;
587     entries[sharedParentTableName_] = "0";
588     expectEntries.push_back(entries);
589     entries = {};
590     entries[sharedParentTableName_] = "2";
591     expectEntries.push_back(entries);
592     CheckCloudData(sharedChildTableName_, true, expectEntries);
593 }
594 
595 /**
596  * @tc.name: CloudSyncTest006
597  * @tc.desc: sync shared table and check version, cloud insert, cloud update
598  * @tc.type: FUNC
599  * @tc.require:
600  * @tc.author: chenchaohao
601  */
602 HWTEST_F(DistributedDBCloudReferenceSyncTest, CloudSyncTest006, TestSize.Level0)
603 {
604     /**
605      * @tc.steps: step1. user insert records then sync, check distributed shared table
606      * @tc.expected: OK.
607      */
608     std::vector<std::string> tableNames = { sharedParentTableName_, sharedChildTableName_ };
609     Query query = Query::Select().FromTable(tableNames);
610     RelationalTestUtils::CloudBlockSync(query, delegate_);
611     InsertCloudSharedTableRecord(0, 1, 1, true);
612     RelationalTestUtils::CloudBlockSync(query, delegate_);
613     CheckDistributedSharedData({"0", "1"});
614 
615     /**
616      * @tc.steps: step2. cloud update records then sync, check distributed shared table
617      * @tc.expected: OK.
618      */
619     UpdateCloudSharedTableRecord(0, 1, 1, true);
620     RelationalTestUtils::CloudBlockSync(query, delegate_);
621     CheckDistributedSharedData({"2", "3"});
622 }
623 
624 /**
625  * @tc.name: CloudSyncTest007
626  * @tc.desc: there is no gid locally, shared table sync
627  * @tc.type: FUNC
628  * @tc.require:
629  * @tc.author: bty
630  */
631 HWTEST_F(DistributedDBCloudReferenceSyncTest, CloudSyncTest007, TestSize.Level0)
632 {
633     /**
634      * @tc.steps: step1. user insert records then sync, check distributed shared table
635      * @tc.expected: OK.
636      */
637     std::vector<std::string> tableNames = { sharedParentTableName_, sharedChildTableName_ };
638     Query query = Query::Select().FromTable(tableNames);
639     RelationalTestUtils::CloudBlockSync(query, delegate_);
640     InsertUserTableRecord(sharedParentTableName_, 1, true, 0, "a_owner");
641     InsertUserTableRecord(sharedChildTableName_, 1, true, 0, "a_owner");
642     std::this_thread::sleep_for(std::chrono::milliseconds(1));
643     InsertCloudSharedTableRecord(0, 1, 1, true);
644     RelationalTestUtils::CloudBlockSync(query, delegate_);
645     CheckSharedDataAfterUpdated({166.0, 166.0}); // 166.0 is the height col val on the cloud
646 }
647 
648 /**
649  * @tc.name: CloudSyncTest008
650  * @tc.desc: sync with dot storeId
651  * @tc.type: FUNC
652  * @tc.require:
653  * @tc.author: zhangqiquan
654  */
655 HWTEST_F(DistributedDBCloudReferenceSyncTest, CloudSyncTest008, TestSize.Level0)
656 {
657     /**
658      * @tc.steps: step1. open store with dot store id
659      * @tc.expected: open ok.
660      */
661     RelationalStoreDelegate::Option option;
662     RelationalStoreDelegate *delegate = nullptr;
663     ASSERT_EQ(mgr_->OpenStore(storePath_, STORE_ID_1 + ".test", option, delegate), DBStatus::OK);
664     ASSERT_NE(delegate, nullptr);
665     EXPECT_EQ(delegate->SetCloudDB(virtualCloudDb_), DBStatus::OK);
666     EXPECT_EQ(delegate->SetIAssetLoader(std::make_shared<VirtualAssetLoader>()), DBStatus::OK);
667     EXPECT_EQ(delegate->CreateDistributedTable(parentTableName_, CLOUD_COOPERATION), DBStatus::OK);
668     EXPECT_EQ(delegate->CreateDistributedTable(childTableName_, CLOUD_COOPERATION), DBStatus::OK);
669     SetReference();
670     DataBaseSchema dataBaseSchema = GetSchema();
671     EXPECT_EQ(delegate->SetCloudDbSchema(dataBaseSchema), DBStatus::OK);
672     /**
673      * @tc.steps: step2. call cloud sync
674      * @tc.expected: sync ok.
675      */
676     std::vector<std::string> tableNames = { parentTableName_, childTableName_ };
677     Query query = Query::Select().FromTable(tableNames);
678     RelationalTestUtils::CloudBlockSync(query, delegate_);
679     /**
680      * @tc.steps: step3. insert data and cloud sync again
681      * @tc.expected: sync ok.
682      */
683     InsertUserTableRecord(parentTableName_, 1);
684     InsertUserTableRecord(childTableName_, 1);
685     RelationalTestUtils::CloudBlockSync(query, delegate_);
686     /**
687      * @tc.steps: step4. close store
688      * @tc.expected: close ok.
689      */
690     EXPECT_EQ(mgr_->CloseStore(delegate), DBStatus::OK);
691 }
692 
ComplexReferenceCheck001SetReference(RelationalStoreDelegate * delegate)693 void ComplexReferenceCheck001SetReference(RelationalStoreDelegate *delegate)
694 {
695     // the reference like this
696     // h <-  a
697     //    b     c
698     //  d   e  f  g
699     std::vector<TableReferenceProperty> tableReferenceProperty;
700     TableReferenceProperty property;
701     property.sourceTableName = "table_d";
702     property.targetTableName = "table_b";
703     property.columns["name"] = "name";
704     tableReferenceProperty.push_back(property);
705 
706     property.sourceTableName = "table_e";
707     property.targetTableName = "table_b";
708     tableReferenceProperty.push_back(property);
709 
710     property.sourceTableName = "table_f";
711     property.targetTableName = "table_c";
712     tableReferenceProperty.push_back(property);
713 
714     property.sourceTableName = "table_g";
715     property.targetTableName = "table_c";
716     tableReferenceProperty.push_back(property);
717 
718     property.sourceTableName = "table_b";
719     property.targetTableName = "table_a";
720     tableReferenceProperty.push_back(property);
721 
722     property.sourceTableName = "table_b";
723     property.targetTableName = "table_h";
724     tableReferenceProperty.push_back(property);
725 
726     property.sourceTableName = "table_c";
727     property.targetTableName = "table_a";
728     tableReferenceProperty.push_back(property);
729 
730     property.sourceTableName = "table_a";
731     property.targetTableName = "table_h";
732     tableReferenceProperty.push_back(property);
733     delegate->SetReference(tableReferenceProperty);
734 }
735 
736 /**
737  * @tc.name: ComplexReferenceCheck001
738  * @tc.desc: sync with complex table reference
739  * @tc.type: FUNC
740  * @tc.require:
741  * @tc.author: zhangqiquan
742  */
743 HWTEST_F(DistributedDBCloudReferenceSyncTest, ComplexReferenceCheck001, TestSize.Level0)
744 {
745     auto tableName = InitMultiTable(8); // 8 table
746     ComplexReferenceCheck001SetReference(delegate_);
747     ASSERT_EQ(delegate_->SetCloudDbSchema(GetSchema(tableName)), DBStatus::OK);
748 
749     std::vector<std::string> tableNames = { "table_a", "table_b", "table_d" };
750     Query query = Query::Select().FromTable(tableNames);
751     RelationalTestUtils::CloudBlockSync(query, delegate_);
752 
753     tableNames = { "table_a", "table_b", "table_c", "table_h" };
754     query = Query::Select().FromTable(tableNames);
755     RelationalTestUtils::CloudBlockSync(query, delegate_, INVALID_ARGS);
756 
757     tableNames = { "table_h", "table_e" };
758     query = Query::Select().FromTable(tableNames);
759     RelationalTestUtils::CloudBlockSync(query, delegate_);
760 
761     tableNames = { "table_e" };
762     query = Query::Select().FromTable(tableNames);
763     RelationalTestUtils::CloudBlockSync(query, delegate_);
764 }
765 
ComplexReferenceCheck002SetReference(RelationalStoreDelegate * delegate)766 void ComplexReferenceCheck002SetReference(RelationalStoreDelegate *delegate)
767 {
768     // the reference like this
769     // a -> b -> c -> d -> e
770     std::vector<TableReferenceProperty> tableReferenceProperty;
771     TableReferenceProperty property;
772     property.sourceTableName = "table_a";
773     property.targetTableName = "table_b";
774     property.columns["name"] = "name";
775     tableReferenceProperty.push_back(property);
776 
777     property.sourceTableName = "table_c";
778     property.targetTableName = "table_d";
779     tableReferenceProperty.push_back(property);
780 
781     property.sourceTableName = "table_d";
782     property.targetTableName = "table_e";
783     tableReferenceProperty.push_back(property);
784 
785     property.sourceTableName = "table_b";
786     property.targetTableName = "table_c";
787     tableReferenceProperty.push_back(property);
788 
789     delegate->SetReference(tableReferenceProperty);
790 }
791 
792 /**
793  * @tc.name: ComplexReferenceCheck002
794  * @tc.desc: sync with complex table reference
795  * @tc.type: FUNC
796  * @tc.require:
797  * @tc.author: zhangqiquan
798  */
799 HWTEST_F(DistributedDBCloudReferenceSyncTest, ComplexReferenceCheck002, TestSize.Level0)
800 {
801     auto tableName = InitMultiTable(5); // 5 table
802     ASSERT_EQ(delegate_->SetCloudDbSchema(GetSchema(tableName)), DBStatus::OK);
803     ComplexReferenceCheck002SetReference(delegate_);
804 
805     std::vector<std::string> tableNames = { "table_a", "table_e" };
806     Query query = Query::Select().FromTable(tableNames);
807     RelationalTestUtils::CloudBlockSync(query, delegate_, DistributedDB::INVALID_ARGS);
808 
809     tableNames = { "table_e", "table_a" };
810     query = Query::Select().FromTable(tableNames);
811     RelationalTestUtils::CloudBlockSync(query, delegate_);
812 
813     tableNames = { "table_a", "table_a_shared" };
814     query = Query::Select().FromTable(tableNames);
815     std::vector<std::string> actualTables;
816     std::set<std::string> addTables;
__anon789e90cf0202(const std::string &table, VBucket &) 817     virtualCloudDb_->ForkQuery([&addTables, &actualTables](const std::string &table, VBucket &) {
818         if (addTables.find(table) != addTables.end()) {
819             return ;
820         }
821         actualTables.push_back(table);
822         addTables.insert(table);
823     });
824     RelationalTestUtils::CloudBlockSync(query, delegate_);
825     virtualCloudDb_->ForkQuery(nullptr);
826     for (const auto &item : actualTables) {
827         LOGW("table is %s", item.c_str());
828     }
829     ASSERT_EQ(actualTables.size(), tableName.size() * 2); // 2 is table size + shared table size
830     // expect res table is table_e table_d ... table_e_shared table_a_shared
831     for (size_t i = 0; i < tableName.size(); ++i) {
832         size_t expectIndex = tableName.size() - 1 - i;
833         size_t expectSharedIndex = expectIndex + tableName.size();
834         const std::string actualTable = actualTables[expectIndex];
835         const std::string actualSharedTable = actualTables[expectSharedIndex];
836         bool equal = (actualTable == tableName[i]);
837         equal = equal && (actualSharedTable == (tableName[i] + "_shared"));
838         LOGW("index %zu expectIndex %zu expectSharedIndex %zu actualTable %s actualSharedTable %s",
839             i, expectIndex, expectSharedIndex, actualTable.c_str(), actualSharedTable.c_str());
840         EXPECT_TRUE(equal);
841     }
842 }
843 
844 /**
845  * @tc.name: ComplexReferenceCheck003
846  * @tc.desc: sync with complex table reference
847  * @tc.type: FUNC
848  * @tc.require:
849  * @tc.author: bty
850  */
851 HWTEST_F(DistributedDBCloudReferenceSyncTest, ComplexReferenceCheck003, TestSize.Level0)
852 {
853     /**
854      * @tc.steps: step1. init reference table, and reopen db
855      * @tc.expected: OK.
856      */
857     auto tableName = InitMultiTable(8); // 8 table
858     ComplexReferenceCheck001SetReference(delegate_);
859     ASSERT_EQ(delegate_->SetCloudDbSchema(GetSchema(tableName)), DBStatus::OK);
860     virtualCloudDb_ = nullptr;
861     EXPECT_EQ(mgr_->CloseStore(delegate_), DBStatus::OK);
862     delegate_ = nullptr;
863     RelationalStoreDelegate::Option option;
864     ASSERT_EQ(mgr_->OpenStore(storePath_, STORE_ID_1, option, delegate_), DBStatus::OK);
865     ASSERT_NE(delegate_, nullptr);
866     virtualCloudDb_ = std::make_shared<VirtualCloudDb>();
867     ASSERT_EQ(delegate_->SetCloudDB(virtualCloudDb_), DBStatus::OK);
868     ASSERT_EQ(delegate_->SetIAssetLoader(std::make_shared<VirtualAssetLoader>()), DBStatus::OK);
869     ASSERT_EQ(delegate_->SetCloudDbSchema(GetSchema(tableName)), DBStatus::OK);
870     tableName = InitMultiTable(8);
871 
872     /**
873      * @tc.steps: step2. init local data, sync
874      * @tc.expected: OK.
875      */
876     int64_t num = 10;
877     InsertUserTableRecord("table_a", num);
878     InsertUserTableRecord("table_b", num);
879     InsertUserTableRecord("table_c", num);
880     std::vector<std::string> tableNames = { "table_a", "table_b", "table_c" };
881     Query query = Query::Select().FromTable(tableNames);
882     RelationalTestUtils::CloudBlockSync(query, delegate_);
883 
884     /**
885      * @tc.steps: step3. operator target table, check source table timeStamp
886      * @tc.expected: OK.
887      */
888     sqlite3_stmt *stmt = nullptr;
889     ASSERT_EQ(SQLiteUtils::GetStatement(db_, "SELECT max(timestamp) FROM " + DBCommon::GetLogTableName("table_c"),
890         stmt), E_OK);
891     ASSERT_EQ(SQLiteUtils::StepWithRetry(stmt, false), SQLiteUtils::MapSQLiteErrno(SQLITE_ROW));
892     int64_t timeStamp = static_cast<int64_t>(sqlite3_column_int64(stmt, 0));
893     int errCode;
894     SQLiteUtils::ResetStatement(stmt, true, errCode);
895     std::string updateSql = "UPDATE table_a SET name = '99' where id = 1";
896     ASSERT_EQ(RelationalTestUtils::ExecSql(db_, updateSql), SQLITE_OK);
897     std::string deleteSql = "DELETE FROM table_a where id = 2";
898     ASSERT_EQ(RelationalTestUtils::ExecSql(db_, deleteSql), SQLITE_OK);
899     updateSql = "UPDATE table_a SET age = '99' where id = 3";
900     ASSERT_EQ(RelationalTestUtils::ExecSql(db_, updateSql), SQLITE_OK);
901     stmt = nullptr;
902     ASSERT_EQ(SQLiteUtils::GetStatement(db_, "SELECT count(*) FROM " + DBCommon::GetLogTableName("table_c") +
903         " WHERE timestamp > '" + std::to_string(timeStamp) + "';", stmt), E_OK);
904     ASSERT_EQ(SQLiteUtils::StepWithRetry(stmt, false), SQLiteUtils::MapSQLiteErrno(SQLITE_ROW));
905     int64_t count = static_cast<int64_t>(sqlite3_column_int64(stmt, 0));
906     SQLiteUtils::ResetStatement(stmt, true, errCode);
907     EXPECT_EQ(count, 2L); // 2 is changed log num
908     RelationalTestUtils::CloudBlockSync(query, delegate_);
909 }
910 
911 /**
912  * @tc.name: ComplexReferenceCheck004
913  * @tc.desc: sync with complex table reference
914  * @tc.type: FUNC
915  * @tc.require:
916  * @tc.author: bty
917  */
918 HWTEST_F(DistributedDBCloudReferenceSyncTest, ComplexReferenceCheck004, TestSize.Level0)
919 {
920     /**
921      * @tc.steps: step1. init table and set reference twice
922      * @tc.expected: OK.
923      */
924     auto tableName = InitMultiTable(8); // 8 table
925     ASSERT_EQ(delegate_->SetCloudDbSchema(GetSchema(tableName)), DBStatus::OK);
926     ComplexReferenceCheck001SetReference(delegate_);
927     ComplexReferenceCheck001SetReference(delegate_);
928 
929     /**
930      * @tc.steps: step2. init local data, sync
931      * @tc.expected: OK.
932      */
933     InsertUserTableRecord("table_b", 10);
934     InsertUserTableRecord("table_d", 10);
935     InsertUserTableRecord("table_e", 10);
936     std::vector<std::string> tableNames = { "table_b", "table_d", "table_e" };
937     Query query = Query::Select().FromTable(tableNames);
938     RelationalTestUtils::CloudBlockSync(query, delegate_);
939 
940     /**
941      * @tc.steps: step3. operator target table, check source table timeStamp
942      * @tc.expected: OK.
943      */
944     sqlite3_stmt *stmt = nullptr;
945     ASSERT_EQ(SQLiteUtils::GetStatement(db_, "SELECT max(timestamp) FROM " + DBCommon::GetLogTableName("table_d"),
946         stmt), E_OK);
947     ASSERT_EQ(SQLiteUtils::StepWithRetry(stmt, false), SQLiteUtils::MapSQLiteErrno(SQLITE_ROW));
948     int64_t timeStamp = static_cast<int64_t>(sqlite3_column_int64(stmt, 0));
949     int errCode;
950     SQLiteUtils::ResetStatement(stmt, true, errCode);
951     std::string updateSql = "UPDATE table_b SET name = '99' where id = 4";
952     ASSERT_EQ(RelationalTestUtils::ExecSql(db_, updateSql), SQLITE_OK);
953     std::string deleteSql = "DELETE FROM table_b where id = 6";
954     ASSERT_EQ(RelationalTestUtils::ExecSql(db_, deleteSql), SQLITE_OK);
955     updateSql = "UPDATE table_b SET age = '99' where id = 7";
956     ASSERT_EQ(RelationalTestUtils::ExecSql(db_, updateSql), SQLITE_OK);
957     stmt = nullptr;
958     ASSERT_EQ(SQLiteUtils::GetStatement(db_, "SELECT count(*) FROM " + DBCommon::GetLogTableName("table_d") +
959         " WHERE timestamp > '" + std::to_string(timeStamp) + "';", stmt), E_OK);
960     ASSERT_EQ(SQLiteUtils::StepWithRetry(stmt, false), SQLiteUtils::MapSQLiteErrno(SQLITE_ROW));
961     int64_t count = static_cast<int64_t>(sqlite3_column_int64(stmt, 0));
962     SQLiteUtils::ResetStatement(stmt, true, errCode);
963     EXPECT_EQ(count, 2L);
964     RelationalTestUtils::CloudBlockSync(query, delegate_);
965 }
966 
967 /**
968  * @tc.name: ComplexReferenceCheck005
969  * @tc.desc: sync with complex table reference
970  * @tc.type: FUNC
971  * @tc.require:
972  * @tc.author: zhangqiquan
973  */
974 HWTEST_F(DistributedDBCloudReferenceSyncTest, ComplexReferenceCheck005, TestSize.Level1)
975 {
976     auto tableName = InitMultiTable(26); // 26 table is alphabet count
977     ASSERT_EQ(delegate_->SetCloudDbSchema(GetSchema(tableName)), DBStatus::OK);
978     std::vector<TableReferenceProperty> tableReferenceProperty;
979     TableReferenceProperty property;
980     property.columns["name"] = "name";
981     for (size_t i = 0; i < tableName.size() - 1; ++i) {
982         property.sourceTableName = tableName[i];
983         property.targetTableName = tableName[i + 1];
984         tableReferenceProperty.push_back(property);
985     }
986     delegate_->SetReference(tableReferenceProperty);
987 
988     std::vector<std::string> tableNames = { "table_e" };
989     Query query = Query::Select().FromTable(tableNames);
990     RelationalTestUtils::CloudBlockSync(query, delegate_);
991 }
992 
993 /**
994  * @tc.name: ComplexReferenceCheck006
995  * @tc.desc: sync with upper table reference
996  * @tc.type: FUNC
997  * @tc.require:
998  * @tc.author: zhangqiquan
999  */
1000 HWTEST_F(DistributedDBCloudReferenceSyncTest, ComplexReferenceCheck006, TestSize.Level1)
1001 {
1002     auto tableName = InitMultiTable(2); // 2 table is alphabet count
1003     ASSERT_EQ(delegate_->SetCloudDbSchema(GetSchema(tableName)), DBStatus::OK);
1004     std::vector<TableReferenceProperty> tableReferenceProperty;
1005     TableReferenceProperty property;
1006     property.columns["name"] = "name";
1007     for (size_t i = 0; i < tableName.size() - 1; ++i) {
1008         property.sourceTableName = tableName[i];
1009         property.targetTableName = DBCommon::ToUpperCase(tableName[i + 1]);
1010         tableReferenceProperty.push_back(property);
1011     }
1012     delegate_->SetReference(tableReferenceProperty);
1013 
1014     std::vector<std::string> tableNames = { "table_a" };
1015     Query query = Query::Select().FromTable(tableNames);
1016     RelationalTestUtils::CloudBlockSync(query, delegate_);
1017 }
1018 
1019 /**
1020  * @tc.name: SetSharedReference001
1021  * @tc.desc: test set shared table
1022  * @tc.type: FUNC
1023  * @tc.require:
1024  * @tc.author: zhangqiquan
1025  */
1026 HWTEST_F(DistributedDBCloudReferenceSyncTest, SetSharedReference001, TestSize.Level0)
1027 {
1028     std::vector<TableReferenceProperty> tableReferenceProperty;
1029     TableReferenceProperty property;
1030     property.columns["name"] = "name";
1031     property.sourceTableName = childTableName_;
1032     property.targetTableName = sharedParentTableName_;
1033     tableReferenceProperty.push_back(property);
1034     EXPECT_EQ(delegate_->SetReference(tableReferenceProperty), NOT_SUPPORT);
1035 
1036     property.sourceTableName = sharedChildTableName_;
1037     property.targetTableName = parentTableName_;
1038     tableReferenceProperty.clear();
1039     tableReferenceProperty.push_back(property);
1040     EXPECT_EQ(delegate_->SetReference(tableReferenceProperty), NOT_SUPPORT);
1041 
1042     property.sourceTableName = sharedChildTableName_;
1043     property.targetTableName = sharedParentTableName_;
1044     tableReferenceProperty.clear();
1045     tableReferenceProperty.push_back(property);
1046     EXPECT_EQ(delegate_->SetReference(tableReferenceProperty), NOT_SUPPORT);
1047 }
1048 }
1049 #endif // RELATIONAL_STORE