summaryrefslogtreecommitdiff
path: root/mysql-test/suite/innodb/t/foreign_key.test
blob: b33fbf60675238ae0746da8b787b839eff3dc168 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
--source include/have_innodb.inc

#
# MDEV-12669 Circular foreign keys cause a loop and OOM upon LOCK TABLE
#
SET FOREIGN_KEY_CHECKS=0;
CREATE TABLE staff (
  staff_id TINYINT UNSIGNED NOT NULL AUTO_INCREMENT,
  store_id TINYINT UNSIGNED NOT NULL,
  PRIMARY KEY  (staff_id),
  KEY idx_fk_store_id (store_id),
  CONSTRAINT fk_staff_store FOREIGN KEY (store_id) REFERENCES store (store_id) ON DELETE RESTRICT ON UPDATE CASCADE
) ENGINE=InnoDB;
CREATE TABLE store (
  store_id TINYINT UNSIGNED NOT NULL AUTO_INCREMENT,
  manager_staff_id TINYINT UNSIGNED NOT NULL,
  PRIMARY KEY  (store_id),
  UNIQUE KEY idx_unique_manager (manager_staff_id),
  CONSTRAINT fk_store_staff FOREIGN KEY (manager_staff_id) REFERENCES staff (staff_id) ON DELETE RESTRICT ON UPDATE CASCADE
) ENGINE=InnoDB;
SET FOREIGN_KEY_CHECKS=DEFAULT;

LOCK TABLE staff WRITE;
UNLOCK TABLES;
DROP TABLES staff, store;

SET FOREIGN_KEY_CHECKS=1;

--echo #
--echo # MDEV-17531 Crash in RENAME TABLE with FOREIGN KEY and FULLTEXT INDEX
--echo #

--disable_query_log
call mtr.add_suppression("InnoDB: Error; possible reasons:");
--enable_query_log

CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB;
CREATE DATABASE best;
CREATE TABLE t3 (a INT PRIMARY KEY,
CONSTRAINT t2_ibfk_1 FOREIGN KEY (a) REFERENCES t1(a)) ENGINE=InnoDB;
CREATE TABLE best.t2 (a INT PRIMARY KEY, b TEXT, FULLTEXT INDEX(b),
FOREIGN KEY (a) REFERENCES test.t1(a)) ENGINE=InnoDB;
--replace_regex /Table '.*t2'/Table 't2'/
--error ER_TABLE_EXISTS_ERROR
RENAME TABLE best.t2 TO test.t2;
SHOW CREATE TABLE best.t2;
DROP DATABASE best;

--echo #
--echo # MDEV-17541 KILL QUERY during lock wait in FOREIGN KEY check hangs
--echo #
connect (fk, localhost, root,,);
INSERT INTO t1 SET a=1;
BEGIN;
DELETE FROM t1;

connection default;
let $ID= `SELECT @id := CONNECTION_ID()`;
send INSERT INTO t3 SET a=1;

connection fk;
# Check that the above SELECT is blocked
let $wait_condition=
  select count(*) = 1 from information_schema.processlist
  where state = 'update' and info = 'INSERT INTO t3 SET a=1';
--source include/wait_condition.inc
let $ignore= `SELECT @id := $ID`;
kill query @id;

connection default;
--error ER_QUERY_INTERRUPTED
reap;
disconnect fk;

DROP TABLE t3,t1;

--echo #
--echo # MDEV-18222 InnoDB: Failing assertion: heap->magic_n == MEM_BLOCK_MAGIC_N
--echo # or ASAN heap-use-after-free in dict_foreign_remove_from_cache upon CHANGE COLUMN
--echo #
CREATE TABLE t1 (a INT, UNIQUE(a), KEY(a)) ENGINE=InnoDB;
ALTER TABLE t1 ADD FOREIGN KEY (a) REFERENCES t1 (a);
SET SESSION FOREIGN_KEY_CHECKS = OFF;
ALTER TABLE t1 CHANGE COLUMN a a TIME NOT NULL;
ALTER TABLE t1 ADD pk INT NOT NULL AUTO_INCREMENT PRIMARY KEY;
ALTER TABLE t1 CHANGE COLUMN a b TIME;
SET SESSION FOREIGN_KEY_CHECKS = ON;
DROP TABLE t1;

--echo #
--echo # MDEV-18256 InnoDB: Failing assertion: heap->magic_n == MEM_BLOCK_MAGIC_N
--echo # upon DROP FOREIGN KEY
--echo #
CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB;
CREATE TABLE t2 (b INT PRIMARY KEY, FOREIGN KEY fk1 (b) REFERENCES t1 (a))
ENGINE=InnoDB;
ALTER TABLE t2 DROP FOREIGN KEY fk1, DROP FOREIGN KEY fk1;
DROP TABLE t2, t1;

CREATE TABLE t1 (f VARCHAR(256)) ENGINE=InnoDB;
SET SESSION FOREIGN_KEY_CHECKS = OFF;
ALTER TABLE t1 ADD FOREIGN KEY (f) REFERENCES non_existing_table (x);
SET SESSION FOREIGN_KEY_CHECKS = ON;
ALTER TABLE t1 ADD FULLTEXT INDEX ft1 (f);
ALTER TABLE t1 ADD FULLTEXT INDEX ft2 (f);
DROP TABLE t1;

CREATE TABLE t1 (f VARCHAR(256), FTS_DOC_ID BIGINT UNSIGNED PRIMARY KEY)
ENGINE=InnoDB;
SET SESSION FOREIGN_KEY_CHECKS = OFF;
ALTER TABLE t1 ADD FOREIGN KEY (f) REFERENCES non_existing_table (x);
SET SESSION FOREIGN_KEY_CHECKS = ON;
ALTER TABLE t1 ADD FULLTEXT INDEX ft1 (f);
ALTER TABLE t1 ADD FULLTEXT INDEX ft2 (f);
DROP TABLE t1;

--echo #
--echo # MDEV-18630 Conditional jump or move depends on uninitialised value
--echo # in ib_push_warning / dict_create_foreign_constraints_low
--echo #
CREATE TABLE t1 (a INT) ENGINE=InnoDB;
--replace_regex /#sql-[0-9_a-f-]*/#sql-temporary/
--error ER_CANT_CREATE_TABLE
ALTER IGNORE TABLE t1 ADD FOREIGN KEY (a) REFERENCES t2 (b);
--replace_regex /#sql-[0-9_a-f-]*/#sql-temporary/
SHOW WARNINGS;
DROP TABLE t1;

--echo #
--echo # MDEV-18139 ALTER IGNORE ... ADD FOREIGN KEY causes bogus error
--echo #
CREATE TABLE t1 (f1 INT, f2 INT, f3 INT, KEY(f1)) ENGINE=InnoDB;
CREATE TABLE t2 (f INT, KEY(f)) ENGINE=InnoDB;
ALTER TABLE t1 ADD FOREIGN KEY (f2) REFERENCES t2 (f);
ALTER IGNORE TABLE t1 ADD FOREIGN KEY (f3) REFERENCES t1 (f1);
DROP TABLE t1, t2;

# MDEV-19092 Server crash when renaming the column when
# FOREIGN_KEY_CHECKS is disabled
CREATE TABLE t1 (a INT, b INT, KEY idx(a)) ENGINE=InnoDB;
SET FOREIGN_KEY_CHECKS= OFF;
ALTER TABLE t1 ADD FOREIGN KEY (a) REFERENCES tx(x);
ALTER TABLE t1 DROP KEY idx;
ALTER TABLE t1 CHANGE a c INT;
# Cleanup
DROP TABLE t1;

CREATE TABLE t1 (f1 INT, f2 INT, f3 INT, KEY idx(f1)) ENGINE=InnoDB;
ALTER TABLE t1 ADD FOREIGN KEY (f2) REFERENCES t1 (f1);
ALTER TABLE t1 ADD COLUMN f INT;
SET FOREIGN_KEY_CHECKS= OFF;
ALTER TABLE t1 DROP KEY idx;
ALTER TABLE t1 ADD KEY idx (f1);
SET FOREIGN_KEY_CHECKS= ON;
ALTER TABLE t1 DROP f3;
ALTER TABLE t1 CHANGE f f3 INT;
# Cleanup
DROP TABLE t1;

SET FOREIGN_KEY_CHECKS=1;

--echo #
--echo # Bug #19471516 SERVER CRASHES WHEN EXECUTING ALTER TABLE
--echo # ADD FOREIGN KEY
--echo #

CREATE TABLE `department` (`department_id` INT, `department_people_fk` INT,
PRIMARY KEY (`department_id`)) engine=innodb;

CREATE TABLE `title` (`title_id` INT, `title_manager_fk` INT,
`title_reporter_fk` INT, PRIMARY KEY (`title_id`)) engine=innodb;

CREATE TABLE `people` (`people_id` INT, PRIMARY KEY (`people_id`)) engine=innodb;

ALTER TABLE `department` ADD FOREIGN KEY (`department_people_fk`) REFERENCES
`people` (`people_id`);

ALTER TABLE `title` ADD FOREIGN KEY (`title_manager_fk`) REFERENCES `people`
(`people_id`);

ALTER TABLE `title` ADD FOREIGN KEY (`title_reporter_fk`) REFERENCES `people`
(`people_id`);

drop table title, department, people;

#
# FK and prelocking:
# child table accesses (reads and writes) wait for locks.
#
create table t1 (a int primary key, b int) engine=innodb;
create table t2 (c int primary key, d int,
  foreign key (d) references t1 (a) on update cascade) engine=innodb;
insert t1 values (1,1),(2,2),(3,3);
insert t2 values (4,1),(5,2),(6,3);
flush table t2 with read lock; # this takes MDL_SHARED_NO_WRITE
connect (con1,localhost,root);
--error ER_ROW_IS_REFERENCED_2
delete from t1 where a=2;
send update t1 set a=10 where a=1;
connection default;
let $wait_condition= select 1 from information_schema.processlist where state='Waiting for table metadata lock';
source include/wait_condition.inc;
unlock tables;
connection con1;
reap;
connection default;
lock table t2 write; # this takes MDL_SHARED_NO_READ_WRITE
connection con1;
send delete from t1 where a=2;
connection default;
let $wait_condition= select 1 from information_schema.processlist where state='Waiting for table metadata lock';
source include/wait_condition.inc;
unlock tables;
connection con1;
--error ER_ROW_IS_REFERENCED_2
reap;
connection default;
unlock tables;
disconnect con1;

# but privileges should not be checked
create user foo;
grant select,update on test.t1 to foo;
connect(foo,localhost,foo);
update t1 set a=30 where a=3;
disconnect foo;
connection default;
select * from t2;
drop table t2, t1;
drop user foo;

--echo #
--echo # MDEV-17595 - Server crashes in copy_data_between_tables or
--echo #              Assertion `thd->transaction.stmt.is_empty() ||
--echo #              (thd->state_flags & Open_tables_state::BACKUPS_AVAIL)'
--echo #              fails in close_tables_for_reopen upon concurrent
--echo #              ALTER TABLE and FLUSH
--echo #
CREATE TABLE t1 (a INT, KEY(a)) ENGINE=InnoDB;
INSERT INTO t1 VALUES(1),(2);
CREATE TABLE t2 (b INT, KEY(b)) ENGINE=InnoDB;
INSERT INTO t2 VALUES(2);
ALTER TABLE t2 ADD FOREIGN KEY(b) REFERENCES t1(a), LOCK=EXCLUSIVE;
DROP TABLE t2, t1;

#
# MDEV-22180 Planner opens unnecessary tables when updated table is referenced by foreign keys
#

create table t1 (pk int primary key, data int) engine=innodb;
insert t1 values (1,1),(2,2),(3,3);
create table t2 (t1_pk int, foreign key (t1_pk) references t1 (pk)) engine=innodb;
insert t2 values (1),(2);
error ER_NO_REFERENCED_ROW_2;
insert t2 values (10);
flush tables;
flush status;
# with ON UPDATE RESTRICT child tables are not opened
update t1 set data=10 where pk+1>10;
show status like '%opened_tab%';
flush tables;
flush status;
# neither are parent tables
update t2 set t1_pk=11 where t1_pk+1>10;
show status like '%opened_tab%';
# under LOCK TABLES
flush tables;
flush status;
lock tables t1 write;
show status like '%opened_tab%';
insert t1 values (4,4);
show status like '%opened_tab%';
unlock tables;
delimiter |;
create function foo() returns int
begin
  insert t1 values (5,5);
  return 5;
end|
delimiter ;|
flush tables;
flush status;
select foo();
show status like '%opened_tab%';
drop function foo;
drop table t2, t1;

#
# End of 10.1 tests
#