@@ -2658,3 +2658,92 @@ def test_issue_160_unknown_mysql_type_bug():
26582658 assert mysql_structure .table_name == 'test_table'
26592659 assert len (mysql_structure .fields ) == 17 # All columns should be parsed
26602660 assert mysql_structure .primary_keys == ['id' , 'col_e' ]
2661+
2662+ def test_truncate_operation_bug_issue_155 ():
2663+ """
2664+ Test to reproduce the bug from issue #155.
2665+
2666+ Bug Description: TRUNCATE operation is not replicated - data is not cleared on ClickHouse side
2667+
2668+ This test should FAIL until the bug is fixed.
2669+ When the bug is present: TRUNCATE will not clear ClickHouse data and the test will FAIL
2670+ When the bug is fixed: TRUNCATE will clear ClickHouse data and the test will PASS
2671+ """
2672+ cfg = config .Settings ()
2673+ cfg .load (CONFIG_FILE )
2674+
2675+ mysql = mysql_api .MySQLApi (
2676+ database = None ,
2677+ mysql_settings = cfg .mysql ,
2678+ )
2679+
2680+ ch = clickhouse_api .ClickhouseApi (
2681+ database = TEST_DB_NAME ,
2682+ clickhouse_settings = cfg .clickhouse ,
2683+ )
2684+
2685+ prepare_env (cfg , mysql , ch )
2686+
2687+ # Create a test table
2688+ mysql .execute (f'''
2689+ CREATE TABLE `{ TEST_TABLE_NAME } ` (
2690+ id int NOT NULL AUTO_INCREMENT,
2691+ name varchar(255),
2692+ age int,
2693+ PRIMARY KEY (id)
2694+ );
2695+ ''' )
2696+
2697+ # Insert test data
2698+ mysql .execute (f"INSERT INTO `{ TEST_TABLE_NAME } ` (name, age) VALUES ('Alice', 25);" , commit = True )
2699+ mysql .execute (f"INSERT INTO `{ TEST_TABLE_NAME } ` (name, age) VALUES ('Bob', 30);" , commit = True )
2700+ mysql .execute (f"INSERT INTO `{ TEST_TABLE_NAME } ` (name, age) VALUES ('Charlie', 35);" , commit = True )
2701+
2702+ # Start replication
2703+ binlog_replicator_runner = BinlogReplicatorRunner ()
2704+ binlog_replicator_runner .run ()
2705+ db_replicator_runner = DbReplicatorRunner (TEST_DB_NAME )
2706+ db_replicator_runner .run ()
2707+
2708+ # Wait for initial replication
2709+ assert_wait (lambda : TEST_DB_NAME in ch .get_databases ())
2710+ ch .execute_command (f'USE `{ TEST_DB_NAME } `' )
2711+ assert_wait (lambda : TEST_TABLE_NAME in ch .get_tables ())
2712+ assert_wait (lambda : len (ch .select (TEST_TABLE_NAME )) == 3 )
2713+
2714+ # Verify data is replicated correctly
2715+ mysql .execute (f"SELECT COUNT(*) FROM `{ TEST_TABLE_NAME } `" )
2716+ mysql_count = mysql .cursor .fetchall ()[0 ][0 ]
2717+ assert mysql_count == 3
2718+
2719+ ch_count = len (ch .select (TEST_TABLE_NAME ))
2720+ assert ch_count == 3
2721+
2722+ # Execute TRUNCATE TABLE in MySQL
2723+ mysql .execute (f"TRUNCATE TABLE `{ TEST_TABLE_NAME } `;" , commit = True )
2724+
2725+ # Verify MySQL table is now empty
2726+ mysql .execute (f"SELECT COUNT(*) FROM `{ TEST_TABLE_NAME } `" )
2727+ mysql_count_after_truncate = mysql .cursor .fetchall ()[0 ][0 ]
2728+ assert mysql_count_after_truncate == 0 , "MySQL table should be empty after TRUNCATE"
2729+
2730+ # Wait for replication to process the TRUNCATE operation
2731+ time .sleep (5 ) # Give some time for the operation to be processed
2732+
2733+ # This is where the bug manifests: ClickHouse table should be empty but it's not
2734+ # When the bug is present, this assertion will FAIL because data is not cleared in ClickHouse
2735+ ch_count_after_truncate = len (ch .select (TEST_TABLE_NAME ))
2736+ assert ch_count_after_truncate == 0 , f"ClickHouse table should be empty after TRUNCATE, but contains { ch_count_after_truncate } records"
2737+
2738+ # Insert new data to verify replication still works after TRUNCATE
2739+ mysql .execute (f"INSERT INTO `{ TEST_TABLE_NAME } ` (name, age) VALUES ('Dave', 40);" , commit = True )
2740+ assert_wait (lambda : len (ch .select (TEST_TABLE_NAME )) == 1 )
2741+
2742+ # Verify the new record
2743+ new_record = ch .select (TEST_TABLE_NAME , where = "name='Dave'" )
2744+ assert len (new_record ) == 1
2745+ assert new_record [0 ]['age' ] == 40
2746+
2747+ # Clean up
2748+ db_replicator_runner .stop ()
2749+ binlog_replicator_runner .stop ()
0 commit comments