1 /*
2 * Copyright (c) 2022 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
16 #include <gtest/gtest.h>
17
18 #include "db_common.h"
19 #include "distributeddb_data_generate_unit_test.h"
20 #include "distributeddb_tools_unit_test.h"
21 #include "log_print.h"
22 #include "relational_store_manager.h"
23 #include "virtual_communicator_aggregator.h"
24
25 using namespace testing::ext;
26 using namespace DistributedDB;
27 using namespace DistributedDBUnitTest;
28 using namespace std;
29
30 namespace {
31 constexpr const char* DB_SUFFIX = ".db";
32 constexpr const char* STORE_ID = "Relational_Store_ID";
33 const std::string DEVICE_A = "DEVICE_A";
34 std::string g_testDir;
35 std::string g_dbDir;
36 DistributedDB::RelationalStoreManager g_mgr(APP_ID, USER_ID);
37 VirtualCommunicatorAggregator* g_communicatorAggregator = nullptr;
38
39 const std::string NORMAL_CREATE_TABLE_SQL = "CREATE TABLE IF NOT EXISTS sync_data(" \
40 "key BLOB NOT NULL UNIQUE," \
41 "value BLOB," \
42 "timestamp INT NOT NULL," \
43 "flag INT NOT NULL," \
44 "device BLOB," \
45 "ori_device BLOB," \
46 "hash_key BLOB PRIMARY KEY NOT NULL," \
47 "w_timestamp INT," \
48 "UNIQUE(device, ori_device));" \
49 "CREATE INDEX key_index ON sync_data (key, flag);";
50
51 const std::string EMPTY_COLUMN_TYPE_CREATE_TABLE_SQL = "CREATE TABLE IF NOT EXISTS student(" \
52 "id INTEGER NOT NULL UNIQUE," \
53 "name TEXT," \
54 "field_1);";
55
56 const std::string NORMAL_CREATE_TABLE_SQL_STUDENT = R""(create table student_1 (
57 id INTEGER PRIMARY KEY,
58 name STRING,
59 level INTGER,
60 score INTGER
61 ))"";
62
FakeOldVersionDB(sqlite3 * db)63 void FakeOldVersionDB(sqlite3 *db)
64 {
65 std::string dropTrigger = "DROP TRIGGER IF EXISTS naturalbase_rdb_student_1_ON_UPDATE;";
66 EXPECT_EQ(RelationalTestUtils::ExecSql(db, dropTrigger), SQLITE_OK);
67
68 std::string oldTrigger = "CREATE TRIGGER naturalbase_rdb_student_1_ON_UPDATE AFTER UPDATE \n"
69 "ON student_1\n"
70 "BEGIN\n"
71 "\t UPDATE naturalbase_rdb_aux_student_1_log SET timestamp=get_sys_time(0), device='', "
72 "flag=0x22 WHERE hash_key=calc_hash(OLD.id) AND flag&0x02=0x02;\n"
73 "END;";
74 EXPECT_EQ(RelationalTestUtils::ExecSql(db, oldTrigger), SQLITE_OK);
75 Key key;
76 DBCommon::StringToVector("log_table_version", key);
77 Value val;
78 DBCommon::StringToVector("1.0", val);
79 EXPECT_EQ(RelationalTestUtils::SetMetaData(db, key, val), SQLITE_OK);
80 }
81 }
82
83 class DistributedDBInterfacesRelationalSyncTest : public testing::Test {
84 public:
85 static void SetUpTestCase(void);
86 static void TearDownTestCase(void);
87 void SetUp() override;
88 void TearDown() override;
89 protected:
90 sqlite3 *db = nullptr;
91 RelationalStoreDelegate *delegate = nullptr;
92 };
93
SetUpTestCase(void)94 void DistributedDBInterfacesRelationalSyncTest::SetUpTestCase(void)
95 {
96 DistributedDBToolsUnitTest::TestDirInit(g_testDir);
97 LOGD("Test dir is %s", g_testDir.c_str());
98 g_dbDir = g_testDir + "/";
99
100 g_communicatorAggregator = new (std::nothrow) VirtualCommunicatorAggregator();
101 ASSERT_TRUE(g_communicatorAggregator != nullptr);
102 RuntimeContext::GetInstance()->SetCommunicatorAggregator(g_communicatorAggregator);
103 }
104
TearDownTestCase(void)105 void DistributedDBInterfacesRelationalSyncTest::TearDownTestCase(void)
106 {
107 RuntimeContext::GetInstance()->SetCommunicatorAggregator(nullptr);
108 }
109
SetUp()110 void DistributedDBInterfacesRelationalSyncTest::SetUp()
111 {
112 DistributedDBToolsUnitTest::PrintTestCaseInfo();
113
114 db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX);
115 ASSERT_NE(db, nullptr);
116 EXPECT_EQ(RelationalTestUtils::ExecSql(db, "PRAGMA journal_mode=WAL;"), SQLITE_OK);
117 EXPECT_EQ(RelationalTestUtils::ExecSql(db, NORMAL_CREATE_TABLE_SQL), SQLITE_OK);
118 RelationalTestUtils::CreateDeviceTable(db, "sync_data", DEVICE_A);
119
120 DBStatus status = g_mgr.OpenStore(g_dbDir + STORE_ID + DB_SUFFIX, STORE_ID, {}, delegate);
121 EXPECT_EQ(status, OK);
122 ASSERT_NE(delegate, nullptr);
123
124 status = delegate->CreateDistributedTable("sync_data");
125 EXPECT_EQ(status, OK);
126 }
127
TearDown()128 void DistributedDBInterfacesRelationalSyncTest::TearDown()
129 {
130 g_mgr.CloseStore(delegate);
131 EXPECT_EQ(sqlite3_close_v2(db), SQLITE_OK);
132 DistributedDBToolsUnitTest::RemoveTestDbFiles(g_testDir);
133 }
134
135 /**
136 * @tc.name: RelationalSyncTest001
137 * @tc.desc: Test with sync interface, table is not a distributed table
138 * @tc.type: FUNC
139 * @tc.require: AR000GK58F
140 * @tc.author: lianhuix
141 */
142 HWTEST_F(DistributedDBInterfacesRelationalSyncTest, RelationalSyncTest001, TestSize.Level1)
143 {
144 std::vector<std::string> devices = {DEVICE_A};
145 Query query = Query::Select("sync_datb");
146 int errCode = delegate->Sync(devices, SyncMode::SYNC_MODE_PUSH_ONLY, query,
__anondd973ae90202(const std::map<std::string, std::vector<TableStatus>> &devicesMap) 147 [&devices](const std::map<std::string, std::vector<TableStatus>> &devicesMap) {
148 EXPECT_EQ(devicesMap.size(), devices.size());
149 }, true);
150
151 EXPECT_EQ(errCode, DISTRIBUTED_SCHEMA_NOT_FOUND);
152 }
153
154 /**
155 * @tc.name: RelationalSyncTest002
156 * @tc.desc: Test with sync interface, query is not support
157 * @tc.type: FUNC
158 * @tc.require: AR000GK58F
159 * @tc.author: lianhuix
160 */
161 HWTEST_F(DistributedDBInterfacesRelationalSyncTest, RelationalSyncTest002, TestSize.Level1)
162 {
163 std::vector<std::string> devices = {DEVICE_A};
164 Query query = Query::Select("sync_data").Like("value", "abc");
165 int errCode = delegate->Sync(devices, SyncMode::SYNC_MODE_PUSH_ONLY, query,
__anondd973ae90302(const std::map<std::string, std::vector<TableStatus>> &devicesMap) 166 [&devices](const std::map<std::string, std::vector<TableStatus>> &devicesMap) {
167 EXPECT_EQ(devicesMap.size(), devices.size());
168 }, true);
169
170 EXPECT_EQ(errCode, NOT_SUPPORT);
171 }
172
173 /**
174 * @tc.name: RelationalSyncTest003
175 * @tc.desc: Test with sync interface, query is invalid format
176 * @tc.type: FUNC
177 * @tc.require: AR000GK58F
178 * @tc.author: lianhuix
179 */
180 HWTEST_F(DistributedDBInterfacesRelationalSyncTest, RelationalSyncTest003, TestSize.Level1)
181 {
182 std::vector<std::string> devices = {DEVICE_A};
183 Query query = Query::Select("sync_data").And().Or().EqualTo("flag", 2);
184 int errCode = delegate->Sync(devices, SyncMode::SYNC_MODE_PUSH_ONLY, query,
__anondd973ae90402(const std::map<std::string, std::vector<TableStatus>> &devicesMap) 185 [&devices](const std::map<std::string, std::vector<TableStatus>> &devicesMap) {
186 EXPECT_EQ(devicesMap.size(), devices.size());
187 }, true);
188
189 EXPECT_EQ(errCode, INVALID_QUERY_FORMAT);
190 }
191
192 /**
193 * @tc.name: RelationalSyncTest004
194 * @tc.desc: Test with sync interface, query use invalid field
195 * @tc.type: FUNC
196 * @tc.require: AR000GK58F
197 * @tc.author: lianhuix
198 */
199 HWTEST_F(DistributedDBInterfacesRelationalSyncTest, RelationalSyncTest004, TestSize.Level1)
200 {
201 std::vector<std::string> devices = {DEVICE_A};
202 Query query = Query::Select("sync_data").EqualTo("fleg", 2);
203 int errCode = delegate->Sync(devices, SyncMode::SYNC_MODE_PUSH_ONLY, query,
__anondd973ae90502(const std::map<std::string, std::vector<TableStatus>> &devicesMap) 204 [&devices](const std::map<std::string, std::vector<TableStatus>> &devicesMap) {
205 EXPECT_EQ(devicesMap.size(), devices.size());
206 }, true);
207
208 EXPECT_EQ(errCode, INVALID_QUERY_FIELD);
209 }
210
211 /**
212 * @tc.name: RelationalSyncTest005
213 * @tc.desc: Test with sync interface, query table has been modified
214 * @tc.type: FUNC
215 * @tc.require: AR000GK58F
216 * @tc.author: lianhuix
217 */
218 HWTEST_F(DistributedDBInterfacesRelationalSyncTest, RelationalSyncTest005, TestSize.Level1)
219 {
220 std::string modifySql = "ALTER TABLE sync_data ADD COLUMN add_field INTEGER;";
221 EXPECT_EQ(RelationalTestUtils::ExecSql(db, modifySql), SQLITE_OK);
222
223 std::vector<std::string> devices = {DEVICE_A};
224 Query query = Query::Select("sync_data");
225 int errCode = delegate->Sync(devices, SyncMode::SYNC_MODE_PUSH_ONLY, query,
__anondd973ae90602(const std::map<std::string, std::vector<TableStatus>> &devicesMap) 226 [&devices](const std::map<std::string, std::vector<TableStatus>> &devicesMap) {
227 EXPECT_EQ(devicesMap.size(), devices.size());
228 }, true);
229
230 EXPECT_EQ(errCode, DISTRIBUTED_SCHEMA_CHANGED);
231 }
232
233 /**
234 * @tc.name: RelationalSyncTest006
235 * @tc.desc: Test with sync interface, query is not set table name
236 * @tc.type: FUNC
237 * @tc.require: AR000GK58F
238 * @tc.author: lianhuix
239 */
240 HWTEST_F(DistributedDBInterfacesRelationalSyncTest, RelationalSyncTest006, TestSize.Level1)
241 {
242 std::vector<std::string> devices = {DEVICE_A};
243 Query query = Query::Select();
244 int errCode = delegate->Sync(devices, SyncMode::SYNC_MODE_PUSH_ONLY, query,
__anondd973ae90702(const std::map<std::string, std::vector<TableStatus>> &devicesMap) 245 [&devices](const std::map<std::string, std::vector<TableStatus>> &devicesMap) {
246 EXPECT_EQ(devicesMap.size(), devices.size());
247 }, true);
248
249 EXPECT_EQ(errCode, NOT_SUPPORT);
250 }
251
252 /**
253 * @tc.name: RelationalSyncTest007
254 * @tc.desc: Test with sync interface, distributed table has empty column type
255 * @tc.type: FUNC
256 * @tc.require: AR000GK58F
257 * @tc.author: lianhuix
258 */
259 HWTEST_F(DistributedDBInterfacesRelationalSyncTest, RelationalSyncTest007, TestSize.Level1)
260 {
261 EXPECT_EQ(RelationalTestUtils::ExecSql(db, EMPTY_COLUMN_TYPE_CREATE_TABLE_SQL), SQLITE_OK);
262 RelationalTestUtils::CreateDeviceTable(db, "student", DEVICE_A);
263
264 DBStatus status = delegate->CreateDistributedTable("student");
265 EXPECT_EQ(status, OK);
266
267 std::vector<std::string> devices = {DEVICE_A};
268 Query query = Query::Select("student");
269 int errCode = delegate->Sync(devices, SyncMode::SYNC_MODE_PUSH_ONLY, query,
__anondd973ae90802(const std::map<std::string, std::vector<TableStatus>> &devicesMap) 270 [&devices](const std::map<std::string, std::vector<TableStatus>> &devicesMap) {
271 EXPECT_EQ(devicesMap.size(), devices.size());
272 }, true);
273
274 EXPECT_EQ(errCode, OK);
275 }
276
277 /**
278 * @tc.name: RelationalSyncTest008
279 * @tc.desc: Test sync with rebuilt table
280 * @tc.type: FUNC
281 * @tc.require: AR000GK58F
282 * @tc.author: lianhuix
283 */
284 HWTEST_F(DistributedDBInterfacesRelationalSyncTest, RelationalSyncTest008, TestSize.Level1)
285 {
286 /**
287 * @tc.steps:step1. Drop sync_data
288 * @tc.expected: step1. ok
289 */
290 std::string dropSql = "DROP TABLE IF EXISTS sync_data;";
291 EXPECT_EQ(RelationalTestUtils::ExecSql(db, dropSql), SQLITE_OK);
292
293 /**
294 * @tc.steps:step2. sync with sync_data
295 * @tc.expected: step2. return INVALID_QUERY_FORMAT
296 */
297 std::vector<std::string> devices = {DEVICE_A};
298 Query query = Query::Select("sync_data");
299 int errCode = delegate->Sync(devices, SyncMode::SYNC_MODE_PUSH_ONLY, query,
__anondd973ae90902(const std::map<std::string, std::vector<TableStatus>> &devicesMap) 300 [&devices](const std::map<std::string, std::vector<TableStatus>> &devicesMap) {
301 EXPECT_EQ(devicesMap.size(), devices.size());
302 }, true);
303 EXPECT_EQ(errCode, DISTRIBUTED_SCHEMA_CHANGED);
304
305 /**
306 * @tc.steps:step3. recreate sync_data
307 * @tc.expected: step3. ok
308 */
309 EXPECT_EQ(RelationalTestUtils::ExecSql(db, NORMAL_CREATE_TABLE_SQL), SQLITE_OK);
310 DBStatus status = delegate->CreateDistributedTable("sync_data");
311 EXPECT_EQ(status, OK);
312
313 /**
314 * @tc.steps:step4. Check trigger
315 * @tc.expected: step4. trigger exists
316 */
317 bool result = false;
318 std::string checkSql = "select * from sqlite_master where type = 'trigger' and tbl_name = 'sync_data';";
319 EXPECT_EQ(RelationalTestUtils::CheckSqlResult(db, checkSql, result), E_OK);
320 EXPECT_EQ(result, true);
321
322 /**
323 * @tc.steps:step5. sync with sync_data
324 * @tc.expected: step5. ok
325 */
326 errCode = delegate->Sync(devices, SyncMode::SYNC_MODE_PUSH_ONLY, query,
__anondd973ae90a02(const std::map<std::string, std::vector<TableStatus>> &devicesMap) 327 [&devices](const std::map<std::string, std::vector<TableStatus>> &devicesMap) {
328 EXPECT_EQ(devicesMap.size(), devices.size());
329 }, true);
330
331 EXPECT_EQ(errCode, OK);
332 }
333
334 /**
335 * @tc.name: RelationalSyncTest009
336 * @tc.desc: Test sync with invalid query
337 * @tc.type: FUNC
338 * @tc.require: AR000GK58F
339 * @tc.author: lianhuix
340 */
341 HWTEST_F(DistributedDBInterfacesRelationalSyncTest, RelationalSyncTest009, TestSize.Level1)
342 {
343 EXPECT_EQ(RelationalTestUtils::ExecSql(db, EMPTY_COLUMN_TYPE_CREATE_TABLE_SQL), SQLITE_OK);
344 RelationalTestUtils::CreateDeviceTable(db, "student", DEVICE_A);
345
346 DBStatus status = delegate->CreateDistributedTable("student");
347 EXPECT_EQ(status, OK);
348
349 std::vector<std::string> devices = {DEVICE_A};
350 Query query = Query::Select("student").EqualTo("$id", 123);
351 status = delegate->Sync(devices, SyncMode::SYNC_MODE_PUSH_ONLY, query,
__anondd973ae90b02(const std::map<std::string, std::vector<TableStatus>> &devicesMap) 352 [&devices](const std::map<std::string, std::vector<TableStatus>> &devicesMap) {
353 EXPECT_EQ(devicesMap.size(), devices.size());
354 }, true);
355 EXPECT_EQ(status, INVALID_QUERY_FORMAT);
356
357 query = Query::Select("student").EqualTo("A$id", 123);
358 status = delegate->Sync(devices, SyncMode::SYNC_MODE_PUSH_ONLY, query,
__anondd973ae90c02(const std::map<std::string, std::vector<TableStatus>> &devicesMap) 359 [&devices](const std::map<std::string, std::vector<TableStatus>> &devicesMap) {
360 EXPECT_EQ(devicesMap.size(), devices.size());
361 }, true);
362 EXPECT_EQ(status, INVALID_QUERY_FORMAT);
363
364 query = Query::Select("student").EqualTo("$.id", 123);
365 status = delegate->Sync(devices, SyncMode::SYNC_MODE_PUSH_ONLY, query,
__anondd973ae90d02(const std::map<std::string, std::vector<TableStatus>> &devicesMap) 366 [&devices](const std::map<std::string, std::vector<TableStatus>> &devicesMap) {
367 EXPECT_EQ(devicesMap.size(), devices.size());
368 }, true);
369
370 EXPECT_EQ(status, OK);
371 }
372
373 /**
374 * @tc.name: RelationalSyncTest010
375 * @tc.desc: Test sync with shcema changed
376 * @tc.type: FUNC
377 * @tc.require: AR000GK58F
378 * @tc.author: lianhuix
379 */
380 HWTEST_F(DistributedDBInterfacesRelationalSyncTest, RelationalSyncTest010, TestSize.Level1)
381 {
382 std::vector<std::string> devices = {DEVICE_A};
383 Query query = Query::Select("sync_data");
384 int errCode = delegate->Sync(devices, SyncMode::SYNC_MODE_PUSH_ONLY, query,
__anondd973ae90e02(const std::map<std::string, std::vector<TableStatus>> &devicesMap) 385 [&devices](const std::map<std::string, std::vector<TableStatus>> &devicesMap) {
386 EXPECT_EQ(devicesMap.size(), devices.size());
387 }, true);
388 EXPECT_EQ(errCode, OK);
389
390 std::string modifySql = "DROP TABLE IF EXISTS sync_data;";
391 EXPECT_EQ(RelationalTestUtils::ExecSql(db, modifySql), SQLITE_OK);
392
393 errCode = delegate->Sync(devices, SyncMode::SYNC_MODE_PUSH_ONLY, query,
__anondd973ae90f02(const std::map<std::string, std::vector<TableStatus>> &devicesMap) 394 [&devices](const std::map<std::string, std::vector<TableStatus>> &devicesMap) {
395 EXPECT_EQ(devicesMap.size(), devices.size());
396 }, true);
397 EXPECT_EQ(errCode, DISTRIBUTED_SCHEMA_CHANGED);
398
399 errCode = delegate->Sync(devices, SyncMode::SYNC_MODE_PUSH_ONLY, query,
__anondd973ae91002(const std::map<std::string, std::vector<TableStatus>> &devicesMap) 400 [&devices](const std::map<std::string, std::vector<TableStatus>> &devicesMap) {
401 EXPECT_EQ(devicesMap.size(), devices.size());
402 }, true);
403 EXPECT_EQ(errCode, DISTRIBUTED_SCHEMA_CHANGED);
404 }
405
406 /**
407 * @tc.name: UpdatePrimaryKeyTest001
408 * @tc.desc: Test update data's primary key
409 * @tc.type: FUNC
410 * @tc.require: AR000GK58F
411 * @tc.author: lianhuix
412 */
413 HWTEST_F(DistributedDBInterfacesRelationalSyncTest, UpdatePrimaryKeyTest001, TestSize.Level1)
414 {
415 EXPECT_EQ(RelationalTestUtils::ExecSql(db, NORMAL_CREATE_TABLE_SQL_STUDENT), SQLITE_OK);
416 RelationalTestUtils::CreateDeviceTable(db, "student_1", DEVICE_A);
417
418 DBStatus status = delegate->CreateDistributedTable("student_1");
419 EXPECT_EQ(status, OK);
420
421 std::string insertSql = "insert into student_1 (id, name, level, score) values (1001, 'xue', 2, 95);";
422 EXPECT_EQ(RelationalTestUtils::ExecSql(db, insertSql), SQLITE_OK);
423
424 std::string updateSql = "update student_1 set id = 1002 where name = 'xue';";
425 EXPECT_EQ(RelationalTestUtils::ExecSql(db, updateSql), SQLITE_OK);
426
427 int cnt = RelationalTestUtils::CheckTableRecords(db, DBConstant::RELATIONAL_PREFIX + "student_1" + "_log");
428 EXPECT_EQ(cnt, 2);
429 }
430
431 /**
432 * @tc.name: UpgradeTriggerTest001
433 * @tc.desc: Test upgrade from old version
434 * @tc.type: FUNC
435 * @tc.require: AR000GK58F
436 * @tc.author: lianhuix
437 */
438 HWTEST_F(DistributedDBInterfacesRelationalSyncTest, UpgradeTriggerTest001, TestSize.Level1)
439 {
440 EXPECT_EQ(RelationalTestUtils::ExecSql(db, NORMAL_CREATE_TABLE_SQL_STUDENT), SQLITE_OK);
441 RelationalTestUtils::CreateDeviceTable(db, "student_1", DEVICE_A);
442
443 DBStatus status = delegate->CreateDistributedTable("student_1");
444 EXPECT_EQ(status, OK);
445
446 EXPECT_EQ(g_mgr.CloseStore(delegate), OK);
447 delegate = nullptr;
448
449 FakeOldVersionDB(db);
450
451 status = g_mgr.OpenStore(g_dbDir + STORE_ID + DB_SUFFIX, STORE_ID, {}, delegate);
452 EXPECT_EQ(status, OK);
453 ASSERT_NE(delegate, nullptr);
454
455 // checkTrigger
456 std::string resultTrigger;
457 int errCode = RelationalTestUtils::ExecSql(db, "SELECT sql FROM sqlite_master WHERE type = ? AND name = ?",
__anondd973ae91102(sqlite3_stmt *stmt) 458 [](sqlite3_stmt *stmt) {
459 (void)SQLiteUtils::BindTextToStatement(stmt, 1, "trigger"); // 1: bind index
460 (void)SQLiteUtils::BindTextToStatement(stmt, 2, "naturalbase_rdb_student_1_ON_UPDATE"); // 2: bind index
461 return E_OK;
462 }, [&resultTrigger](sqlite3_stmt *stmt) {
463 (void)SQLiteUtils::GetColumnTextValue(stmt, 0, resultTrigger);
464 return E_OK;
465 });
466 EXPECT_EQ(errCode, E_OK);
467 LOGD("result trigger: %s", resultTrigger.c_str());
468 std::string expectTrigger = "CREATE TRIGGER naturalbase_rdb_student_1_ON_UPDATE AFTER UPDATE \n"
469 "ON student_1\n"
470 "BEGIN\n"
471 "\t UPDATE naturalbase_rdb_aux_student_1_log SET data_key=-1,timestamp=get_sys_time(0), device='',"
472 " flag=0x03 WHERE hash_key=calc_hash(OLD.id) AND flag&0x02=0x02;\n"
473 "\t INSERT OR REPLACE INTO naturalbase_rdb_aux_student_1_log VALUES (NEW.rowid, '', '', get_sys_time(0), "
474 "get_sys_time(0), CASE WHEN (calc_hash(NEW.id) != calc_hash(NEW.id)) " \
475 "THEN 0x02 ELSE 0x22 END, calc_hash(NEW.id));\n"
476 "END";
477 EXPECT_TRUE(resultTrigger == expectTrigger);
478 }