@@ -1057,6 +1057,122 @@ def test_string_primary_key(monkeypatch):
1057
1057
binlog_replicator_runner .stop ()
1058
1058
1059
1059
1060
+ def test_if_exists_if_not_exists (monkeypatch ):
1061
+ monkeypatch .setattr (DbReplicator , 'INITIAL_REPLICATION_BATCH_SIZE' , 1 )
1062
+
1063
+ cfg = config .Settings ()
1064
+ cfg .load (CONFIG_FILE )
1065
+
1066
+ mysql = mysql_api .MySQLApi (
1067
+ database = None ,
1068
+ mysql_settings = cfg .mysql ,
1069
+ )
1070
+
1071
+ ch = clickhouse_api .ClickhouseApi (
1072
+ database = TEST_DB_NAME ,
1073
+ clickhouse_settings = cfg .clickhouse ,
1074
+ )
1075
+
1076
+ prepare_env (cfg , mysql , ch )
1077
+
1078
+ binlog_replicator_runner = BinlogReplicatorRunner ()
1079
+ binlog_replicator_runner .run ()
1080
+ db_replicator_runner = DbReplicatorRunner (TEST_DB_NAME )
1081
+ db_replicator_runner .run ()
1082
+
1083
+ assert_wait (lambda : TEST_DB_NAME in ch .get_databases ())
1084
+
1085
+ mysql .execute (f"CREATE TABLE IF NOT EXISTS { TEST_DB_NAME } .{ TEST_TABLE_NAME } (id int NOT NULL, PRIMARY KEY(id));" )
1086
+ mysql .execute (f"CREATE TABLE IF NOT EXISTS { TEST_TABLE_NAME } (id int NOT NULL, PRIMARY KEY(id));" )
1087
+ mysql .execute (f"CREATE TABLE IF NOT EXISTS { TEST_DB_NAME } .{ TEST_TABLE_NAME_2 } (id int NOT NULL, PRIMARY KEY(id));" )
1088
+ mysql .execute (f"CREATE TABLE IF NOT EXISTS { TEST_TABLE_NAME_2 } (id int NOT NULL, PRIMARY KEY(id));" )
1089
+ mysql .execute (f"DROP TABLE IF EXISTS { TEST_DB_NAME } .{ TEST_TABLE_NAME } ;" )
1090
+ mysql .execute (f"DROP TABLE IF EXISTS { TEST_TABLE_NAME } ;" )
1091
+
1092
+ ch .execute_command (f'USE { TEST_DB_NAME } ' )
1093
+
1094
+ assert_wait (lambda : TEST_TABLE_NAME_2 in ch .get_tables ())
1095
+ assert_wait (lambda : TEST_TABLE_NAME not in ch .get_tables ())
1096
+
1097
+ db_replicator_runner .stop ()
1098
+ binlog_replicator_runner .stop ()
1099
+
1100
+
1101
+ def test_percona_migration (monkeypatch ):
1102
+ monkeypatch .setattr (DbReplicator , 'INITIAL_REPLICATION_BATCH_SIZE' , 1 )
1103
+
1104
+ cfg = config .Settings ()
1105
+ cfg .load (CONFIG_FILE )
1106
+
1107
+ mysql = mysql_api .MySQLApi (
1108
+ database = None ,
1109
+ mysql_settings = cfg .mysql ,
1110
+ )
1111
+
1112
+ ch = clickhouse_api .ClickhouseApi (
1113
+ database = TEST_DB_NAME ,
1114
+ clickhouse_settings = cfg .clickhouse ,
1115
+ )
1116
+
1117
+ prepare_env (cfg , mysql , ch )
1118
+
1119
+ mysql .execute (f'''
1120
+ CREATE TABLE { TEST_TABLE_NAME } (
1121
+ `id` int NOT NULL,
1122
+ PRIMARY KEY (`id`));
1123
+ ''' )
1124
+
1125
+ mysql .execute (
1126
+ f"INSERT INTO { TEST_TABLE_NAME } (id) VALUES (42)" ,
1127
+ commit = True ,
1128
+ )
1129
+
1130
+ binlog_replicator_runner = BinlogReplicatorRunner ()
1131
+ binlog_replicator_runner .run ()
1132
+ db_replicator_runner = DbReplicatorRunner (TEST_DB_NAME )
1133
+ db_replicator_runner .run ()
1134
+
1135
+ assert_wait (lambda : TEST_DB_NAME in ch .get_databases ())
1136
+
1137
+ ch .execute_command (f'USE { TEST_DB_NAME } ' )
1138
+
1139
+ assert_wait (lambda : TEST_TABLE_NAME in ch .get_tables ())
1140
+ assert_wait (lambda : len (ch .select (TEST_TABLE_NAME )) == 1 )
1141
+
1142
+ # Perform 'pt-online-schema-change' style migration to add a column
1143
+ # This is a subset of what happens when the following command is run:
1144
+ # pt-online-schema-change --alter "ADD COLUMN c1 INT" D=$TEST_DB_NAME,t=$TEST_TABLE_NAME,h=0.0.0.0,P=3306,u=root,p=admin --execute
1145
+ mysql .execute (f'''
1146
+ CREATE TABLE `{ TEST_DB_NAME } `.`_{ TEST_TABLE_NAME } _new` (
1147
+ `id` int NOT NULL,
1148
+ PRIMARY KEY (`id`)
1149
+ )''' )
1150
+
1151
+ mysql .execute (
1152
+ f"ALTER TABLE `{ TEST_DB_NAME } `.`_{ TEST_TABLE_NAME } _new` ADD COLUMN c1 INT;" )
1153
+
1154
+ mysql .execute (
1155
+ f"INSERT LOW_PRIORITY IGNORE INTO `{ TEST_DB_NAME } `.`_{ TEST_TABLE_NAME } _new` (`id`) SELECT `id` FROM `{ TEST_DB_NAME } `.`{ TEST_TABLE_NAME } ` LOCK IN SHARE MODE;" ,
1156
+ commit = True ,
1157
+ )
1158
+
1159
+ mysql .execute (
1160
+ f"RENAME TABLE `{ TEST_DB_NAME } `.`{ TEST_TABLE_NAME } ` TO `{ TEST_DB_NAME } `.`_{ TEST_TABLE_NAME } _old`, `{ TEST_DB_NAME } `.`_{ TEST_TABLE_NAME } _new` TO `{ TEST_DB_NAME } `.`{ TEST_TABLE_NAME } `;" )
1161
+
1162
+ mysql .execute (
1163
+ f"DROP TABLE IF EXISTS `{ TEST_DB_NAME } `.`_{ TEST_TABLE_NAME } _old`;" )
1164
+
1165
+ mysql .execute (
1166
+ f"INSERT INTO { TEST_TABLE_NAME } (id, c1) VALUES (43, 1)" ,
1167
+ commit = True ,
1168
+ )
1169
+
1170
+ assert_wait (lambda : len (ch .select (TEST_TABLE_NAME )) == 2 )
1171
+
1172
+ db_replicator_runner .stop ()
1173
+ binlog_replicator_runner .stop ()
1174
+
1175
+
1060
1176
def test_parse_mysql_table_structure ():
1061
1177
query = "CREATE TABLE IF NOT EXISTS user_preferences_portal (\n \t \t \t id char(36) NOT NULL,\n \t \t \t category varchar(50) DEFAULT NULL,\n \t \t \t deleted tinyint(1) DEFAULT 0,\n \t \t \t date_entered datetime DEFAULT NULL,\n \t \t \t date_modified datetime DEFAULT NULL,\n \t \t \t assigned_user_id char(36) DEFAULT NULL,\n \t \t \t contents longtext DEFAULT NULL\n \t \t ) ENGINE=InnoDB DEFAULT CHARSET=utf8"
1062
1178
@@ -1065,3 +1181,4 @@ def test_parse_mysql_table_structure():
1065
1181
structure = converter .parse_mysql_table_structure (query )
1066
1182
1067
1183
assert structure .table_name == 'user_preferences_portal'
1184
+
0 commit comments