1#
2# Tests of foreign keys that need a debug build or debug_sync feature.
3#
4
5--source include/have_debug.inc
6--source include/have_debug_sync.inc
7# Some parts of the test require enabled binary log.
8--source include/have_log_bin.inc
9
10SET @saved_binlog_format= @@SESSION.binlog_format;
11
12SET SESSION debug= '+d,skip_dd_table_access_check';
13SET @@foreign_key_checks= DEFAULT;
14
15--echo #
16--echo # WL#6929: Move FOREIGN KEY constraints to the global data dictionary
17--echo #
18
19--echo # Test coverage for foreign key name generation. Should be removed
20--echo # or rewritten when WL#7141 is pushed.
21
22CREATE TABLE t1(a INT PRIMARY KEY);
23CREATE TABLE t2(a INT PRIMARY KEY);
24CREATE TABLE t3(a INT PRIMARY KEY, b INT, c INT);
25
26ALTER TABLE t3 ADD FOREIGN KEY (b) REFERENCES t1(a);
27# InnoDB generated name (until after WL#6599)
28SHOW CREATE TABLE t3;
29# Server generated name (until after WL#6599)
30SELECT fk.name FROM mysql.foreign_keys AS fk, mysql.tables AS t
31WHERE fk.table_id = t.id AND t.name = 't3';
32
33ALTER TABLE t3 ADD FOREIGN KEY (c) REFERENCES t1(a);
34# InnoDB generated name (until after WL#6599)
35SHOW CREATE TABLE t3;
36# Server generated name (until after WL#6599)
37SELECT fk.name FROM mysql.foreign_keys AS fk, mysql.tables AS t
38WHERE fk.table_id = t.id AND t.name = 't3';
39
40ALTER TABLE t3 ADD FOREIGN KEY (b) REFERENCES t1(a);
41# InnoDB generated name (until after WL#6599)
42SHOW CREATE TABLE t3;
43# Server generated name (until after WL#6599)
44SELECT fk.name FROM mysql.foreign_keys AS fk, mysql.tables AS t
45WHERE fk.table_id = t.id AND t.name = 't3';
46
47ALTER TABLE t3 DROP FOREIGN KEY t3_ibfk_1;
48# InnoDB generated name (until after WL#6599)
49SHOW CREATE TABLE t3;
50# Server generated name (until after WL#6599)
51SELECT fk.name FROM mysql.foreign_keys AS fk, mysql.tables AS t
52WHERE fk.table_id = t.id AND t.name = 't3';
53
54ALTER TABLE t3 ADD FOREIGN KEY (b) REFERENCES t1(a);
55# InnoDB generated name (until after WL#6599)
56SHOW CREATE TABLE t3;
57# Server generated name (until after WL#6599)
58SELECT fk.name FROM mysql.foreign_keys AS fk, mysql.tables AS t
59WHERE fk.table_id = t.id AND t.name = 't3';
60
61DROP TABLE t3, t2, t1;
62
63CREATE TABLE t1(a INT PRIMARY KEY);
64CREATE TABLE name567890123456789012345678901234567890123456789012345678901234(a INT PRIMARY KEY, b INT);
65
66--error ER_TOO_LONG_IDENT
67ALTER TABLE name567890123456789012345678901234567890123456789012345678901234
68ADD FOREIGN KEY(b) REFERENCES t1(a);
69
70DROP TABLE name567890123456789012345678901234567890123456789012345678901234, t1;
71
72
73--echo #
74--echo # WL#6049: Meta data locking for foreign keys.
75--echo #
76
77--echo #
78--echo # Normal CT will set the FK unique constraint name.
79--echo #
80
81CREATE TABLE parent(pk INTEGER PRIMARY KEY, j INTEGER,
82  UNIQUE KEY my_key (j));
83CREATE TABLE child(pk INTEGER PRIMARY KEY, fk INTEGER,
84  FOREIGN KEY (fk) REFERENCES parent(j));
85SELECT unique_constraint_name FROM mysql.foreign_keys
86  WHERE referenced_table_name LIKE 'parent';
87
88DROP TABLES child, parent;
89
90--echo #
91--echo # CT introducing a missing parent will update the FK unique constraint name in the child.
92--echo #
93
94SET @@foreign_key_checks= 0;
95CREATE TABLE child(pk INTEGER PRIMARY KEY, fk INTEGER,
96  FOREIGN KEY (fk) REFERENCES parent(j));
97
98--echo # An index is created for the FK, but the unique constraint name is NULL.
99SELECT name FROM mysql.indexes
100  WHERE table_id = (SELECT id from mysql.tables WHERE name LIKE 'child');
101SELECT unique_constraint_name FROM mysql.foreign_keys
102  WHERE referenced_table_name LIKE 'parent';
103
104CREATE TABLE parent(pk INTEGER PRIMARY KEY, j INTEGER,
105  UNIQUE KEY my_key (j));
106SET @@foreign_key_checks= 1;
107
108--echo # After creating the parent, the unique constraint name is updated.
109SELECT unique_constraint_name FROM mysql.foreign_keys
110  WHERE referenced_table_name LIKE 'parent';
111
112DROP TABLES child, parent;
113
114--echo #
115--echo # CTL does not copy FKs from the source table.
116--echo #
117
118CREATE TABLE parent(pk INTEGER PRIMARY KEY, j INTEGER,
119  UNIQUE KEY my_key (j));
120CREATE TABLE child(pk INTEGER PRIMARY KEY, fk INTEGER,
121  FOREIGN KEY (fk) REFERENCES parent(j));
122SELECT unique_constraint_name FROM mysql.foreign_keys
123  WHERE referenced_table_name LIKE 'parent';
124
125CREATE TABLE child_copy LIKE child;
126
127--echo ## The index is re-created for the new table.
128SELECT name FROM mysql.indexes
129  WHERE table_id = (SELECT id from mysql.tables WHERE name LIKE 'child');
130SELECT name FROM mysql.indexes
131  WHERE table_id = (SELECT id from mysql.tables WHERE name LIKE 'child_copy');
132
133--echo ## ... but not the constraint.
134SELECT unique_constraint_name FROM mysql.foreign_keys
135  WHERE referenced_table_name LIKE 'parent';
136
137DROP TABLES child, child_copy, parent;
138
139--echo #
140--echo # CTL introducing a missing parent will update the FK in the child.
141--echo #
142
143SET @@foreign_key_checks= 0;
144CREATE TABLE child(pk INTEGER PRIMARY KEY, fk INTEGER,
145  FOREIGN KEY (fk) REFERENCES parent(j));
146
147--echo ## An index is created for the FK, but the unique constraint name is NULL.
148SELECT name FROM mysql.indexes
149  WHERE table_id = (SELECT id from mysql.tables WHERE name LIKE 'parent');
150SELECT unique_constraint_name FROM mysql.foreign_keys
151  WHERE referenced_table_name LIKE 'parent';
152
153CREATE TABLE parent_base(pk INTEGER PRIMARY KEY, j INTEGER,
154  UNIQUE KEY my_key (j));
155CREATE TABLE parent LIKE parent_base;
156SET @@foreign_key_checks= 1;
157
158--echo ## After creating the parent, the unique constraint name is updated.
159SELECT unique_constraint_name FROM mysql.foreign_keys
160  WHERE referenced_table_name LIKE 'parent';
161
162DROP TABLE child, parent_base, parent;
163
164--echo #
165--echo # CTS will update the unique constraint name in its FK info.
166--echo #
167
168CREATE TABLE source(pk INTEGER PRIMARY KEY, j INTEGER);
169INSERT INTO source VALUES (1, 1);
170
171CREATE TABLE parent(pk INTEGER PRIMARY KEY, j INTEGER,
172  UNIQUE KEY my_key(j));
173INSERT INTO parent VALUES (2, 1);
174
175SET @@SESSION.binlog_format=STATEMENT;
176CREATE TABLE child(pk INTEGER PRIMARY KEY, fk INTEGER,
177  FOREIGN KEY (fk) REFERENCES parent(j)) AS SELECT pk, j AS fk FROM source;
178SET SESSION binlog_format= @saved_binlog_format;
179SELECT * FROM child;
180
181--echo ## An index is created for the FK, and the unique constraint name is updated.
182SELECT name FROM mysql.indexes
183  WHERE table_id = (SELECT id from mysql.tables WHERE name LIKE 'child');
184SELECT unique_constraint_name FROM mysql.foreign_keys
185  WHERE referenced_table_name LIKE 'parent';
186
187DROP TABLES source, child, parent;
188
189--echo #
190--echo # CTS introducing a missing parent will update the FK in the child.
191--echo #
192
193SET @@foreign_key_checks= 0;
194CREATE TABLE source(pk INTEGER PRIMARY KEY, j INTEGER);
195INSERT INTO source VALUES (1, 1);
196
197CREATE TABLE child(pk INTEGER PRIMARY KEY, fk INTEGER,
198  FOREIGN KEY (fk) REFERENCES parent(j));
199
200--echo ## An index is created for the FK, but the unique constraint name is NULL.
201SELECT name FROM mysql.indexes
202  WHERE table_id = (SELECT id from mysql.tables WHERE name LIKE 'child');
203SELECT unique_constraint_name FROM mysql.foreign_keys
204  WHERE referenced_table_name LIKE 'parent';
205
206SET @@SESSION.binlog_format=STATEMENT;
207CREATE TABLE parent(pk INTEGER PRIMARY KEY, j INTEGER,
208  UNIQUE KEY my_key(j)) AS SELECT * FROM source;
209SET SESSION binlog_format= @saved_binlog_format;
210SELECT * FROM child;
211SET @@foreign_key_checks= 1;
212
213--echo ## After creating the parent, the unique constraint name is updated.
214SELECT unique_constraint_name FROM mysql.foreign_keys
215  WHERE referenced_table_name LIKE 'parent';
216
217DROP TABLES source, child, parent;
218
219--echo #
220--echo # RENAME will update FK information in both children and parents.
221--echo #
222
223CREATE TABLE parent(pk INTEGER PRIMARY KEY, j INTEGER,
224  UNIQUE KEY parent_key(j));
225
226CREATE TABLE child(pk INTEGER PRIMARY KEY, k INTEGER, fk INTEGER,
227  FOREIGN KEY (fk) REFERENCES parent(j), UNIQUE KEY child_key(k));
228--echo # Constraint is enforced.
229--error ER_NO_REFERENCED_ROW_2
230INSERT INTO child VALUES (1, 2, 3);
231
232CREATE TABLE grandchild(pk INTEGER PRIMARY KEY, fk INTEGER,
233  FOREIGN KEY (fk) REFERENCES child(k));
234--echo # Constraint is enforced.
235--error ER_NO_REFERENCED_ROW_2
236INSERT INTO grandchild VALUES (1, 2);
237
238SET @@foreign_key_checks= 0;
239CREATE TABLE orphan_grandchild(pk INTEGER PRIMARY KEY, fk INTEGER,
240  FOREIGN KEY (fk) REFERENCES siebling(k));
241SET @@foreign_key_checks= 1;
242
243--echo # FK definitions before rename:
244
245SELECT name, unique_constraint_name, referenced_table_schema, referenced_table_name
246  FROM mysql.foreign_keys
247  WHERE referenced_table_schema LIKE 'test';
248
249RENAME TABLE child TO siebling;
250
251--echo # After the rename, we see that:
252--echo # 1. The name of the constraint is changed to 'siebling_ibfk...'.
253--echo # 2. The referenced table name of the grandchild is changed to 'siebling'.
254--echo # 3. The unique constraint name of the orphan_grandchild is corrected.
255SELECT name, unique_constraint_name, referenced_table_schema, referenced_table_name
256  FROM mysql.foreign_keys
257  WHERE referenced_table_schema LIKE 'test';
258
259--echo # Constraint is still enforced.
260--error ER_NO_REFERENCED_ROW_2
261INSERT INTO siebling VALUES (1, 2, 3);
262
263--echo # Constraint is still enforced.
264--error ER_NO_REFERENCED_ROW_2
265INSERT INTO grandchild VALUES (1, 2);
266
267--echo # Constraint is enforced here too.
268--error ER_NO_REFERENCED_ROW_2
269INSERT INTO orphan_grandchild VALUES (1, 2);
270
271DROP TABLE grandchild;
272DROP TABLE orphan_grandchild;
273DROP TABLE siebling;
274DROP TABLE parent;
275
276--echo # When processing LOCK TABLES, we will prelock even
277--echo # when F_K_C = 0.
278--echo #
279
280CREATE TABLE parent(pk INTEGER PRIMARY KEY, j INTEGER,
281  UNIQUE KEY parent_key(j));
282
283CREATE TABLE child(pk INTEGER PRIMARY KEY, fk INTEGER,
284  FOREIGN KEY (fk) REFERENCES parent(j) ON DELETE CASCADE);
285
286SET @@foreign_key_checks= 0;
287LOCK TABLES parent WRITE;
288
289--echo # There are two metadata locks because the child has
290--echo # two different FK roles wrt. the parent. Note that
291--echo # the locks are stronger for LOCK TABLES.
292SELECT OBJECT_TYPE, OBJECT_SCHEMA, OBJECT_NAME, COLUMN_NAME,
293  LOCK_TYPE FROM performance_schema.metadata_locks
294  WHERE OBJECT_NAME LIKE 'child'
295  ORDER BY OBJECT_TYPE, OBJECT_SCHEMA, OBJECT_NAME, COLUMN_NAME, LOCK_TYPE;
296
297--echo # From another connection, verify that child is locked.
298--connect (con_1, localhost, root)
299SET @@session.lock_wait_timeout= 1;
300--error ER_LOCK_WAIT_TIMEOUT
301INSERT INTO child VALUES (1, 1);
302--disconnect con_1
303
304--connection default
305UNLOCK TABLES;
306SET @@foreign_key_checks= 1;
307
308--echo # Now, the locks are gone.
309SELECT LOCK_TYPE FROM performance_schema.metadata_locks
310  WHERE OBJECT_NAME LIKE 'child';
311
312DROP TABLE child;
313DROP TABLE parent;
314
315--echo #
316--echo # A prepared statement will become invalid if a child table
317--echo # is modified between executions of the prepared statement.
318--echo #
319
320CREATE TABLE parent(pk INTEGER PRIMARY KEY, j INTEGER,
321  UNIQUE KEY parent_key(j));
322
323CREATE TABLE child(pk INTEGER PRIMARY KEY, fk INTEGER,
324  FOREIGN KEY (fk) REFERENCES parent(j) ON DELETE CASCADE);
325
326PREPARE stmt FROM 'DELETE FROM parent WHERE pk = ?';
327
328SELECT COUNT_REPREPARE, COUNT_EXECUTE
329  FROM performance_schema.prepared_statements_instances
330  WHERE STATEMENT_NAME LIKE 'stmt';
331
332SET @a= 1;
333EXECUTE stmt USING @a;
334
335--echo # No reprepare for first execution.
336SELECT COUNT_REPREPARE, COUNT_EXECUTE
337  FROM performance_schema.prepared_statements_instances
338  WHERE STATEMENT_NAME LIKE 'stmt';
339
340--echo # Altering child will trigger reprepare on next execution.
341ALTER TABLE child ADD COLUMN (j INTEGER);
342
343EXECUTE stmt USING @a;
344
345--echo # Statement has been reprepared for second execution.
346SELECT COUNT_REPREPARE, COUNT_EXECUTE
347  FROM performance_schema.prepared_statements_instances
348  WHERE STATEMENT_NAME LIKE 'stmt';
349
350EXECUTE stmt USING @a;
351
352--echo # Cache version for the prelock entry is updated, so no
353--echo # reprepare for third execution.
354SELECT COUNT_REPREPARE, COUNT_EXECUTE
355  FROM performance_schema.prepared_statements_instances
356  WHERE STATEMENT_NAME LIKE 'stmt';
357
358DROP TABLE child;
359DROP TABLE parent;
360
361
362--echo #
363--echo # Check situations where there are multiple foreign keys
364--echo # referring the same table.
365--echo #
366
367CREATE TABLE parent(pk INTEGER PRIMARY KEY, i INTEGER, j INTEGER,
368  UNIQUE KEY parent_i_key(i), UNIQUE KEY parent_j_key(j));
369
370CREATE TABLE child(pk INTEGER PRIMARY KEY, fk_i INTEGER, fk_j INTEGER,
371  FOREIGN KEY (fk_i) REFERENCES parent(i),
372  FOREIGN KEY (fk_j) REFERENCES parent(j));
373
374ALTER TABLE child RENAME TO siebling;
375
376DROP TABLES siebling, parent;
377
378--echo #
379--echo # Rename a table multiple times in the same statement.
380--echo #
381
382CREATE TABLE parent(pk INTEGER PRIMARY KEY, i INTEGER,
383  UNIQUE KEY parent_key(i));
384
385CREATE TABLE child(pk INTEGER PRIMARY KEY, fk_i INTEGER,
386  FOREIGN KEY (fk_i) REFERENCES parent(i));
387
388RENAME TABLE parent TO mother, mother TO father;
389
390SELECT name, unique_constraint_name, referenced_table_schema, referenced_table_name
391  FROM mysql.foreign_keys
392  WHERE referenced_table_schema LIKE 'test';
393
394RENAME TABLE child TO sister, sister TO brother;
395
396SELECT name, unique_constraint_name, referenced_table_schema, referenced_table_name
397  FROM mysql.foreign_keys
398  WHERE referenced_table_schema LIKE 'test';
399
400RENAME TABLE father TO mother, brother TO sister, mother TO parent, sister TO child;
401
402SELECT name, unique_constraint_name, referenced_table_schema, referenced_table_name
403  FROM mysql.foreign_keys
404  WHERE referenced_table_schema LIKE 'test';
405
406DROP TABLES child, parent;
407
408--echo #
409--echo # Let a RENAME statement introduce a missing parent and rename
410--echo # it further as well.
411--echo #
412
413SET @@foreign_key_checks= 0;
414CREATE TABLE child(pk INTEGER PRIMARY KEY, fk_i INTEGER,
415  FOREIGN KEY (fk_i) REFERENCES mother(i));
416SET @@foreign_key_checks= 1;
417
418CREATE TABLE parent(pk INTEGER PRIMARY KEY, i INTEGER,
419  UNIQUE KEY parent_key(i));
420
421SELECT name, unique_constraint_name, referenced_table_schema, referenced_table_name
422  FROM mysql.foreign_keys
423  WHERE referenced_table_schema LIKE 'test';
424
425RENAME TABLE parent TO mother, mother TO father;
426
427SELECT name, unique_constraint_name, referenced_table_schema, referenced_table_name
428  FROM mysql.foreign_keys
429  WHERE referenced_table_schema LIKE 'test';
430
431DROP TABLES child, father;
432
433--echo #
434--echo # Rename a parent with a child having several FKs to it.
435--echo #
436
437CREATE TABLE parent(pk INTEGER PRIMARY KEY, i INTEGER, j INTEGER,
438  UNIQUE KEY parent_i_key(i),
439  UNIQUE KEY parent_j_key(j));
440
441CREATE TABLE child(pk INTEGER PRIMARY KEY, fk_i INTEGER, fk_j INTEGER,
442  FOREIGN KEY (fk_i) REFERENCES parent(i),
443  FOREIGN KEY (fk_j) REFERENCES parent(j));
444
445SELECT name, unique_constraint_name, referenced_table_schema, referenced_table_name
446  FROM mysql.foreign_keys
447  WHERE referenced_table_schema LIKE 'test';
448
449RENAME TABLE parent TO mother;
450
451SELECT name, unique_constraint_name, referenced_table_schema, referenced_table_name
452  FROM mysql.foreign_keys
453  WHERE referenced_table_schema LIKE 'test';
454
455DROP TABLES child, mother;
456
457
458--echo #
459--echo # ALTER TABLE RENAME and complex ALTER TABLE RENAME involving
460--echo # self-referncing foreign key.
461--echo #
462CREATE TABLE self (pk INT PRIMARY KEY, fk INT, FOREIGN KEY(fk) REFERENCES self(pk));
463SELECT name, unique_constraint_name, referenced_table_schema, referenced_table_name
464  FROM mysql.foreign_keys
465  WHERE referenced_table_schema LIKE 'test';
466ALTER TABLE self RENAME TO self2;
467SELECT name, unique_constraint_name, referenced_table_schema, referenced_table_name
468  FROM mysql.foreign_keys
469  WHERE referenced_table_schema LIKE 'test';
470ALTER TABLE self2 RENAME TO self3, ADD COLUMN i INT;
471SELECT name, unique_constraint_name, referenced_table_schema, referenced_table_name
472  FROM mysql.foreign_keys
473  WHERE referenced_table_schema LIKE 'test';
474DROP TABLE self3;
475
476--echo #
477--echo # Drop a schema with tables referencing/being referenced by tables
478--echo # in a different schema.
479--echo #
480
481CREATE TABLE parent(pk INTEGER PRIMARY KEY, i INTEGER,
482  UNIQUE KEY parent_i_key(i));
483
484SET @@foreign_key_checks= 0;
485CREATE TABLE grandchild(pk INTEGER PRIMARY KEY, fk_i INTEGER,
486  FOREIGN KEY (fk_i) REFERENCES s1.child(i));
487SET @@foreign_key_checks= 1;
488
489SELECT name, unique_constraint_name, referenced_table_schema, referenced_table_name
490  FROM mysql.foreign_keys
491  WHERE referenced_table_schema LIKE 's1';
492
493CREATE SCHEMA s1;
494CREATE TABLE s1.child(pk INTEGER PRIMARY KEY, i INTEGER, fk_i INTEGER,
495  UNIQUE KEY child_i_key(i),
496  FOREIGN KEY (fk_i) REFERENCES test.parent(i));
497
498SELECT name, unique_constraint_name, referenced_table_schema, referenced_table_name
499  FROM mysql.foreign_keys
500  WHERE referenced_table_schema LIKE 'test';
501
502SELECT name, unique_constraint_name, referenced_table_schema, referenced_table_name
503  FROM mysql.foreign_keys
504  WHERE referenced_table_schema LIKE 's1';
505
506--error ER_FK_CANNOT_DROP_PARENT
507DROP SCHEMA s1;
508
509SET @@foreign_key_checks= 0;
510DROP SCHEMA s1;
511SET @@foreign_key_checks= 1;
512
513SELECT name, unique_constraint_name, referenced_table_schema, referenced_table_name
514  FROM mysql.foreign_keys
515  WHERE referenced_table_schema LIKE 'test';
516
517SELECT name, unique_constraint_name, referenced_table_schema, referenced_table_name
518  FROM mysql.foreign_keys
519  WHERE referenced_table_schema LIKE 's1';
520
521--echo # Skip FK to parent.
522CREATE SCHEMA s1;
523CREATE TABLE s1.child(pk INTEGER PRIMARY KEY, i INTEGER,
524  UNIQUE KEY child_i_key(i));
525
526SELECT name, unique_constraint_name, referenced_table_schema, referenced_table_name
527  FROM mysql.foreign_keys
528  WHERE referenced_table_schema LIKE 's1';
529
530--error ER_FK_CANNOT_DROP_PARENT
531DROP SCHEMA s1;
532
533SET @@foreign_key_checks= 0;
534DROP SCHEMA s1;
535SET @@foreign_key_checks= 1;
536
537SELECT name, unique_constraint_name, referenced_table_schema, referenced_table_name
538  FROM mysql.foreign_keys
539  WHERE referenced_table_schema LIKE 's1';
540
541DROP TABLE grandchild;
542
543--echo # No FK from grandchild.
544CREATE SCHEMA s1;
545CREATE TABLE s1.child(pk INTEGER PRIMARY KEY, fk_i INTEGER);
546
547SELECT name, unique_constraint_name, referenced_table_schema, referenced_table_name
548  FROM mysql.foreign_keys
549  WHERE referenced_table_schema LIKE 'test';
550
551--echo # Introduce FK to parent.
552ALTER TABLE s1.child ADD FOREIGN KEY (fk_i) REFERENCES test.parent(i);
553
554SELECT name, unique_constraint_name, referenced_table_schema, referenced_table_name
555  FROM mysql.foreign_keys
556  WHERE referenced_table_schema LIKE 'test';
557
558DROP SCHEMA s1;
559
560DROP TABLE parent;
561
562
563--echo #
564--echo # Trigger an error in Foreign_key_parents_invalidator::invalidate().
565--echo #
566
567CREATE TABLE parent(pk INTEGER PRIMARY KEY, i INTEGER,
568  UNIQUE KEY parent_key(i));
569
570CREATE TABLE child(pk INTEGER PRIMARY KEY, fk_i INTEGER,
571  FOREIGN KEY (fk_i) REFERENCES parent(i));
572
573SELECT name, unique_constraint_name, referenced_table_schema, referenced_table_name
574  FROM mysql.foreign_keys
575  WHERE referenced_table_schema LIKE 'test';
576
577SET @@session.debug= '+d,fail_while_invalidating_fk_parents';
578ALTER TABLE child RENAME TO siebling;
579SET @@session.debug= '-d,fail_while_invalidating_fk_parents';
580
581SELECT name, unique_constraint_name, referenced_table_schema, referenced_table_name
582  FROM mysql.foreign_keys
583  WHERE referenced_table_schema LIKE 'test';
584
585DROP TABLE siebling, parent;
586
587
588--echo #
589--echo # Coverage for various corner cases when figuring out unique_constraint_name.
590--echo #
591CREATE TABLE parent (i INT, j INT, PRIMARY KEY (i), UNIQUE u(i,j));
592CREATE TABLE child (i INT, j INT, FOREIGN KEY (i, j) REFERENCES parent (i, j));
593SELECT name, unique_constraint_name, referenced_table_schema, referenced_table_name
594  FROM mysql.foreign_keys
595  WHERE referenced_table_schema LIKE 'test';
596ALTER TABLE parent RENAME KEY u TO u1;
597SELECT name, unique_constraint_name, referenced_table_schema, referenced_table_name
598  FROM mysql.foreign_keys
599  WHERE referenced_table_schema LIKE 'test';
600DROP TABLE child, parent;
601
602CREATE TABLE parent (i INT, j INT, k INT, PRIMARY KEY (i), UNIQUE u(j), UNIQUE u1(i,j), UNIQUE u2(i,j,k));
603CREATE TABLE child (i INT, j INT, k INT, FOREIGN KEY (i, j, k) REFERENCES parent (i, j, k));
604SELECT name, unique_constraint_name, referenced_table_schema, referenced_table_name
605  FROM mysql.foreign_keys
606  WHERE referenced_table_schema LIKE 'test';
607ALTER TABLE parent RENAME KEY u2 TO u3;
608SELECT name, unique_constraint_name, referenced_table_schema, referenced_table_name
609  FROM mysql.foreign_keys
610  WHERE referenced_table_schema LIKE 'test';
611DROP TABLE child, parent;
612
613CREATE TABLE parent (i INT, j INT,
614                     d INT GENERATED ALWAYS AS (i) VIRTUAL,
615                     e INT GENERATED ALWAYS AS (j) VIRTUAL,
616                     PRIMARY KEY (i), UNIQUE u(i,d), UNIQUE u1(i,j,e));
617CREATE TABLE child (i INT, j INT, FOREIGN KEY (i, j) REFERENCES parent (i, j));
618SELECT name, unique_constraint_name, referenced_table_schema, referenced_table_name
619  FROM mysql.foreign_keys
620  WHERE referenced_table_schema LIKE 'test';
621ALTER TABLE parent RENAME KEY u1 TO u2;
622SELECT name, unique_constraint_name, referenced_table_schema, referenced_table_name
623  FROM mysql.foreign_keys
624  WHERE referenced_table_schema LIKE 'test';
625DROP TABLE child, parent;
626
627CREATE TABLE parent (i INT, a VARCHAR(10), b VARCHAR(10),
628                     PRIMARY KEY (i), UNIQUE u(i,a(5)), UNIQUE u1(i,a,b(5)));
629CREATE TABLE child (i INT, a VARCHAR(10), FOREIGN KEY (i, a) REFERENCES parent (i, a));
630SELECT name, unique_constraint_name, referenced_table_schema, referenced_table_name
631  FROM mysql.foreign_keys
632  WHERE referenced_table_schema LIKE 'test';
633ALTER TABLE parent RENAME KEY u1 TO u2;
634SELECT name, unique_constraint_name, referenced_table_schema, referenced_table_name
635  FROM mysql.foreign_keys
636  WHERE referenced_table_schema LIKE 'test';
637DROP TABLE child, parent;
638
639CREATE TABLE self (i INT, j INT, i2 INT, j2 INT, PRIMARY KEY (i), UNIQUE u(i,j),
640                   FOREIGN KEY (i2, j2) REFERENCES self (i, j));
641SELECT name, unique_constraint_name, referenced_table_schema, referenced_table_name
642  FROM mysql.foreign_keys
643  WHERE referenced_table_schema LIKE 'test';
644ALTER TABLE self RENAME KEY u TO u1;
645SELECT name, unique_constraint_name, referenced_table_schema, referenced_table_name
646  FROM mysql.foreign_keys
647  WHERE referenced_table_schema LIKE 'test';
648DROP TABLE self;
649
650CREATE TABLE self (i INT, j INT, k INT, i2 INT, j2 INT, k2 INT,
651                   PRIMARY KEY (i), UNIQUE u(j), UNIQUE u1(i,j), UNIQUE u2(i,j,k),
652                   FOREIGN KEY (i2, j2, k2) REFERENCES self (i, j, k));
653SELECT name, unique_constraint_name, referenced_table_schema, referenced_table_name
654  FROM mysql.foreign_keys
655  WHERE referenced_table_schema LIKE 'test';
656ALTER TABLE self RENAME KEY u2 TO u3;
657SELECT name, unique_constraint_name, referenced_table_schema, referenced_table_name
658  FROM mysql.foreign_keys
659  WHERE referenced_table_schema LIKE 'test';
660DROP TABLE self;
661
662CREATE TABLE self (i INT, j INT, i2 INT, j2 INT,
663                   d INT GENERATED ALWAYS AS (i) VIRTUAL,
664                   e INT GENERATED ALWAYS AS (j) VIRTUAL,
665                     PRIMARY KEY (i), UNIQUE u(i,d), UNIQUE u1(i,j,e),
666                     FOREIGN KEY (i2, j2) REFERENCES self (i, j));
667SELECT name, unique_constraint_name, referenced_table_schema, referenced_table_name
668  FROM mysql.foreign_keys
669  WHERE referenced_table_schema LIKE 'test';
670ALTER TABLE self RENAME KEY u1 TO u2;
671SELECT name, unique_constraint_name, referenced_table_schema, referenced_table_name
672  FROM mysql.foreign_keys
673  WHERE referenced_table_schema LIKE 'test';
674DROP TABLE self;
675
676CREATE TABLE self (i INT, a VARCHAR(10), b VARCHAR(10), i2 INT, a2 VARCHAR(10),
677                   PRIMARY KEY (i), UNIQUE u(i,a(5)), UNIQUE u1(i,a,b(5)),
678                   FOREIGN KEY (i2, a2) REFERENCES self (i, a));
679SELECT name, unique_constraint_name, referenced_table_schema, referenced_table_name
680  FROM mysql.foreign_keys
681  WHERE referenced_table_schema LIKE 'test';
682ALTER TABLE self RENAME KEY u1 TO u2;
683SELECT name, unique_constraint_name, referenced_table_schema, referenced_table_name
684  FROM mysql.foreign_keys
685  WHERE referenced_table_schema LIKE 'test';
686DROP TABLE self;
687
688
689# Restore defaults.
690SET @@foreign_key_checks= DEFAULT;
691SET SESSION debug= '-d,skip_dd_table_access_check';
692
693--echo #
694--echo # Part of systemic test coverage for metadata locks related to foreign
695--echo # keys acquired by various DDL statements which requires debug_sync.
696--echo #
697--echo # The main part of this coverage resides in foreign_key.test.
698--echo #
699
700--enable_connect_log
701connect (con1, localhost, root,,);
702connection default;
703
704--echo #
705--echo # 7) ALTER TABLE ... INPLACE
706--echo #
707
708--echo # 7.1) ALTER TABLE ... ADD FOREIGN KEY ... INPLACE must start by
709--echo #      acquiring SU lock on parent table.
710CREATE TABLE parent (pk INT PRIMARY KEY);
711CREATE TABLE child (fk INT);
712
713SET DEBUG_SYNC="alter_table_inplace_after_lock_downgrade SIGNAL reached WAIT_FOR go";
714SET FOREIGN_KEY_CHECKS=0;
715--send ALTER TABLE child ADD CONSTRAINT fk FOREIGN KEY (fk) REFERENCES parent (pk), ALGORITHM=INPLACE;
716
717connection con1;
718SET DEBUG_SYNC="now WAIT_FOR reached";
719
720--echo # DML on parent is still possible at this point.
721INSERT INTO parent VALUES (1);
722
723--echo # But not DDL.
724SET @old_lock_wait_timeout= @@lock_wait_timeout;
725SET @@lock_wait_timeout= 1;
726--error ER_LOCK_WAIT_TIMEOUT
727ALTER TABLE parent ADD COLUMN a INT;
728SET @@lock_wait_timeout= @old_lock_wait_timeout;
729
730SET DEBUG_SYNC="now SIGNAL go";
731
732connection default;
733--echo # Reap ALTER TABLE
734--reap
735SET FOREIGN_KEY_CHECKS=1;
736ALTER TABLE child DROP FOREIGN KEY fk;
737
738--echo #
739--echo # 8) ALTER TABLE ... COPY
740--echo #
741
742--echo # 8.1) ALTER TABLE ... ADD FOREIGN KEY ... COPY must start by
743--echo #      acquiring SU lock on parent table.
744
745SET DEBUG_SYNC="alter_table_copy_after_lock_upgrade SIGNAL reached WAIT_FOR go";
746--send ALTER TABLE child ADD CONSTRAINT fk FOREIGN KEY (fk) REFERENCES parent (pk), ALGORITHM=COPY;
747
748connection con1;
749SET DEBUG_SYNC="now WAIT_FOR reached";
750
751--echo # DML on parent is still possible at this point.
752INSERT INTO parent VALUES (2);
753
754--echo # But not DDL.
755SET @old_lock_wait_timeout= @@lock_wait_timeout;
756SET @@lock_wait_timeout= 1;
757--error ER_LOCK_WAIT_TIMEOUT
758ALTER TABLE parent ADD COLUMN a INT;
759SET @@lock_wait_timeout= @old_lock_wait_timeout;
760
761SET DEBUG_SYNC="now SIGNAL go";
762
763connection default;
764--echo # Reap ALTER TABLE
765--reap
766
767SET DEBUG_SYNC="RESET";
768
769ALTER TABLE child DROP FOREIGN KEY fk;
770
771--echo # 8.1') ALTER TABLE ... ADD FOREIGN KEY ... COPY due to workaround
772--echo #       must upgrade SU lock on parent table SRO lock.
773
774SET DEBUG_SYNC="alter_after_copy_table SIGNAL reached WAIT_FOR go";
775--send ALTER TABLE child ADD CONSTRAINT fk FOREIGN KEY (fk) REFERENCES parent (pk), ALGORITHM=COPY;
776
777connection con1;
778SET DEBUG_SYNC="now WAIT_FOR reached";
779
780--echo # SELECT on parent is still possible at this point.
781SELECT * FROM parent;
782
783--echo # But not changes.
784SET @old_lock_wait_timeout= @@lock_wait_timeout;
785SET @@lock_wait_timeout= 1;
786--error ER_LOCK_WAIT_TIMEOUT
787DELETE FROM parent;
788SET @@lock_wait_timeout= @old_lock_wait_timeout;
789
790SET DEBUG_SYNC="now SIGNAL go";
791
792connection default;
793--echo # Reap ALTER TABLE
794--reap
795
796SET DEBUG_SYNC="RESET";
797
798DROP TABLES child, parent;
799
800connection con1;
801disconnect con1;
802--source include/wait_until_disconnected.inc
803connection default;
804--disable_connect_log
805